@payez/next-mvp 4.8.1 → 4.8.3
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/api-handlers/admin/audit.js +13 -21
- package/dist/api-handlers/admin/sessions.js +59 -45
- package/dist/api-handlers/admin/stats.js +1 -1
- package/dist/api-handlers/admin/users.js +15 -23
- package/dist/api-handlers/admin/vibe-data.d.ts +5 -0
- package/dist/api-handlers/admin/vibe-data.js +5 -0
- 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/pages/login/page.js +28 -28
- package/dist/pages/settings/EnhancedSettingsPage.js +17 -17
- package/dist/vibe/client.d.ts +1 -1
- package/dist/vibe/client.js +2 -1
- package/dist/vibe/filters.d.ts +36 -0
- package/dist/vibe/filters.js +47 -0
- package/dist/vibe/generic.js +2 -1
- 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 +223 -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 +341 -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 +240 -251
- package/src/api-handlers/admin/vibe-data.ts +338 -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/revocation-fields.ts +16 -16
- 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 +1141 -1141
- 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/service-unavailable/page.tsx +63 -63
- 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 +878 -877
- package/src/vibe/enterprise-auth.ts +208 -208
- package/src/vibe/errors.ts +209 -209
- package/src/vibe/filters.ts +52 -0
- package/src/vibe/generic.ts +340 -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
|
@@ -1,200 +1,200 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { useState } from 'react';
|
|
4
|
-
import { useAuthConfig } from '../../client/AuthContext';
|
|
5
|
-
import { FederatedProvider } from '@/types/auth';
|
|
6
|
-
import { FederatedAuthSection } from './FederatedAuthSection';
|
|
7
|
-
import { TraditionalAuthSection } from './TraditionalAuthSection';
|
|
8
|
-
|
|
9
|
-
interface Props {
|
|
10
|
-
onFederatedSignUp?: (provider: FederatedProvider) => void;
|
|
11
|
-
onTraditionalSignUp?: (email: string, password: string, confirmPassword: string) => Promise<void>;
|
|
12
|
-
isLoading?: boolean;
|
|
13
|
-
error?: string | null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function ModeAwareSignupPage({
|
|
17
|
-
onFederatedSignUp,
|
|
18
|
-
onTraditionalSignUp,
|
|
19
|
-
isLoading = false,
|
|
20
|
-
error = null,
|
|
21
|
-
}: Props) {
|
|
22
|
-
const config = useAuthConfig();
|
|
23
|
-
const [email, setEmail] = useState('');
|
|
24
|
-
const [password, setPassword] = useState('');
|
|
25
|
-
const [confirmPassword, setConfirmPassword] = useState('');
|
|
26
|
-
const [localLoading, setLocalLoading] = useState(false);
|
|
27
|
-
|
|
28
|
-
const handleFederatedClick = (provider: FederatedProvider) => {
|
|
29
|
-
onFederatedSignUp?.(provider);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const handleTraditionalSubmit = async (e: React.FormEvent) => {
|
|
33
|
-
e.preventDefault();
|
|
34
|
-
if (!onTraditionalSignUp) return;
|
|
35
|
-
|
|
36
|
-
if (password !== confirmPassword) {
|
|
37
|
-
alert('Passwords do not match');
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
setLocalLoading(true);
|
|
42
|
-
try {
|
|
43
|
-
await onTraditionalSignUp(email, password, confirmPassword);
|
|
44
|
-
} finally {
|
|
45
|
-
setLocalLoading(false);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// Same change as ModeAwareLoginPage: read the independent flags, not the single mode.
|
|
50
|
-
// Leaving signup on `mode` would have made sign-in and sign-up disagree about what the
|
|
51
|
-
// client offers - the worse half of a half-migration.
|
|
52
|
-
const isFederated = config.allowFederatedLogin !== false && config.providers.length > 0;
|
|
53
|
-
const isTraditional = config.allowTraditionalLogin !== false;
|
|
54
|
-
const totalLoading = isLoading || localLoading;
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<>
|
|
58
|
-
{error && (
|
|
59
|
-
<div
|
|
60
|
-
className="mb-6 px-4 py-3 rounded-lg"
|
|
61
|
-
style={{
|
|
62
|
-
background: 'var(--color-error, #ef4444)',
|
|
63
|
-
color: 'white',
|
|
64
|
-
}}
|
|
65
|
-
>
|
|
66
|
-
{error}
|
|
67
|
-
</div>
|
|
68
|
-
)}
|
|
69
|
-
|
|
70
|
-
{/* Federated Only Mode */}
|
|
71
|
-
{isFederated && (
|
|
72
|
-
<FederatedAuthSection
|
|
73
|
-
providers={config.providers}
|
|
74
|
-
onProviderClick={handleFederatedClick}
|
|
75
|
-
isLoading={totalLoading}
|
|
76
|
-
/>
|
|
77
|
-
)}
|
|
78
|
-
|
|
79
|
-
{/* Traditional Only Mode */}
|
|
80
|
-
{isTraditional && config.enableEmailSignup && (
|
|
81
|
-
<form onSubmit={handleTraditionalSubmit} className="space-y-4">
|
|
82
|
-
<div>
|
|
83
|
-
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
|
|
84
|
-
Email Address
|
|
85
|
-
</label>
|
|
86
|
-
<input
|
|
87
|
-
type="email"
|
|
88
|
-
value={email}
|
|
89
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
90
|
-
placeholder="you@example.com"
|
|
91
|
-
disabled={totalLoading}
|
|
92
|
-
required
|
|
93
|
-
className="w-full px-4 py-3 rounded-lg border transition-colors focus:outline-none focus:ring-2 disabled:opacity-50"
|
|
94
|
-
style={{
|
|
95
|
-
border: '1px solid var(--border-default)',
|
|
96
|
-
color: 'var(--text-primary)',
|
|
97
|
-
background: 'var(--bg-default)',
|
|
98
|
-
}}
|
|
99
|
-
/>
|
|
100
|
-
</div>
|
|
101
|
-
|
|
102
|
-
<div>
|
|
103
|
-
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
|
|
104
|
-
Password
|
|
105
|
-
</label>
|
|
106
|
-
<input
|
|
107
|
-
type="password"
|
|
108
|
-
value={password}
|
|
109
|
-
onChange={(e) => setPassword(e.target.value)}
|
|
110
|
-
placeholder="••••••••"
|
|
111
|
-
disabled={totalLoading}
|
|
112
|
-
required
|
|
113
|
-
className="w-full px-4 py-3 rounded-lg border transition-colors focus:outline-none focus:ring-2 disabled:opacity-50"
|
|
114
|
-
style={{
|
|
115
|
-
border: '1px solid var(--border-default)',
|
|
116
|
-
color: 'var(--text-primary)',
|
|
117
|
-
background: 'var(--bg-default)',
|
|
118
|
-
}}
|
|
119
|
-
/>
|
|
120
|
-
</div>
|
|
121
|
-
|
|
122
|
-
<div>
|
|
123
|
-
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
|
|
124
|
-
Confirm Password
|
|
125
|
-
</label>
|
|
126
|
-
<input
|
|
127
|
-
type="password"
|
|
128
|
-
value={confirmPassword}
|
|
129
|
-
onChange={(e) => setConfirmPassword(e.target.value)}
|
|
130
|
-
placeholder="••••••••"
|
|
131
|
-
disabled={totalLoading}
|
|
132
|
-
required
|
|
133
|
-
className="w-full px-4 py-3 rounded-lg border transition-colors focus:outline-none focus:ring-2 disabled:opacity-50"
|
|
134
|
-
style={{
|
|
135
|
-
border: '1px solid var(--border-default)',
|
|
136
|
-
color: 'var(--text-primary)',
|
|
137
|
-
background: 'var(--bg-default)',
|
|
138
|
-
}}
|
|
139
|
-
/>
|
|
140
|
-
</div>
|
|
141
|
-
|
|
142
|
-
<button
|
|
143
|
-
type="submit"
|
|
144
|
-
disabled={totalLoading}
|
|
145
|
-
className="w-full py-3 px-4 rounded-lg font-semibold focus:outline-none focus:ring-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors mt-6"
|
|
146
|
-
style={{
|
|
147
|
-
border: '1px solid var(--border-default)',
|
|
148
|
-
color: 'white',
|
|
149
|
-
background: 'var(--color-primary, #10b981)',
|
|
150
|
-
}}
|
|
151
|
-
>
|
|
152
|
-
{totalLoading ? 'Creating Account...' : 'Create Account'}
|
|
153
|
-
</button>
|
|
154
|
-
</form>
|
|
155
|
-
)}
|
|
156
|
-
|
|
157
|
-
{/* PAY-2334: same three states as the login page. Not answered yet -> neutral text; read failed -> say so;
|
|
158
|
-
only an ANSWERED "nothing offered" falls through to the branch below. */}
|
|
159
|
-
{!isFederated && !isTraditional && config.settingsStatus === 'loading' && (
|
|
160
|
-
<div role="status" className="px-4 py-3 rounded-lg text-sm text-left" style={{ color: 'var(--text-secondary, #6b7280)' }}>
|
|
161
|
-
<p>Loading sign-up options…</p>
|
|
162
|
-
</div>
|
|
163
|
-
)}
|
|
164
|
-
|
|
165
|
-
{!isFederated && !isTraditional && config.settingsStatus === 'failed' && (
|
|
166
|
-
<div
|
|
167
|
-
role="alert"
|
|
168
|
-
className="px-4 py-3 rounded-lg text-sm text-left"
|
|
169
|
-
style={{
|
|
170
|
-
border: '1px solid var(--border-default, #e5e7eb)',
|
|
171
|
-
color: 'var(--text-primary, #111827)',
|
|
172
|
-
}}
|
|
173
|
-
>
|
|
174
|
-
<p className="font-semibold">Could not load sign-up options.</p>
|
|
175
|
-
<p className="mt-1">Please reload the page. If it keeps happening, contact an administrator.</p>
|
|
176
|
-
</div>
|
|
177
|
-
)}
|
|
178
|
-
|
|
179
|
-
{/* PAY-2341: ANSWERED, and nothing is offered. This branch used to be labelled "Hybrid Mode - Show both" and
|
|
180
|
-
rendered the federated section plus the email sign-up form on the same "neither" condition, so a client with no
|
|
181
|
-
sign-up method showed a working-looking form. Say so, as the login page does (ModeAwareLoginPage). */}
|
|
182
|
-
{!isFederated && !isTraditional && (config.settingsStatus ?? 'ready') === 'ready' && (
|
|
183
|
-
<div
|
|
184
|
-
role="alert"
|
|
185
|
-
className="px-4 py-3 rounded-lg text-sm text-left"
|
|
186
|
-
style={{
|
|
187
|
-
border: '1px solid var(--border-default, #e5e7eb)',
|
|
188
|
-
color: 'var(--text-primary, #111827)',
|
|
189
|
-
}}
|
|
190
|
-
>
|
|
191
|
-
<p className="font-semibold">Sign-up is not available for this application.</p>
|
|
192
|
-
<p className="mt-1">
|
|
193
|
-
No sign-up method is enabled for this client. An administrator needs to enable
|
|
194
|
-
a federated provider or username and password sign-in.
|
|
195
|
-
</p>
|
|
196
|
-
</div>
|
|
197
|
-
)}
|
|
198
|
-
</>
|
|
199
|
-
);
|
|
200
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { useState } from 'react';
|
|
4
|
+
import { useAuthConfig } from '../../client/AuthContext';
|
|
5
|
+
import { FederatedProvider } from '@/types/auth';
|
|
6
|
+
import { FederatedAuthSection } from './FederatedAuthSection';
|
|
7
|
+
import { TraditionalAuthSection } from './TraditionalAuthSection';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
onFederatedSignUp?: (provider: FederatedProvider) => void;
|
|
11
|
+
onTraditionalSignUp?: (email: string, password: string, confirmPassword: string) => Promise<void>;
|
|
12
|
+
isLoading?: boolean;
|
|
13
|
+
error?: string | null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function ModeAwareSignupPage({
|
|
17
|
+
onFederatedSignUp,
|
|
18
|
+
onTraditionalSignUp,
|
|
19
|
+
isLoading = false,
|
|
20
|
+
error = null,
|
|
21
|
+
}: Props) {
|
|
22
|
+
const config = useAuthConfig();
|
|
23
|
+
const [email, setEmail] = useState('');
|
|
24
|
+
const [password, setPassword] = useState('');
|
|
25
|
+
const [confirmPassword, setConfirmPassword] = useState('');
|
|
26
|
+
const [localLoading, setLocalLoading] = useState(false);
|
|
27
|
+
|
|
28
|
+
const handleFederatedClick = (provider: FederatedProvider) => {
|
|
29
|
+
onFederatedSignUp?.(provider);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const handleTraditionalSubmit = async (e: React.FormEvent) => {
|
|
33
|
+
e.preventDefault();
|
|
34
|
+
if (!onTraditionalSignUp) return;
|
|
35
|
+
|
|
36
|
+
if (password !== confirmPassword) {
|
|
37
|
+
alert('Passwords do not match');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setLocalLoading(true);
|
|
42
|
+
try {
|
|
43
|
+
await onTraditionalSignUp(email, password, confirmPassword);
|
|
44
|
+
} finally {
|
|
45
|
+
setLocalLoading(false);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Same change as ModeAwareLoginPage: read the independent flags, not the single mode.
|
|
50
|
+
// Leaving signup on `mode` would have made sign-in and sign-up disagree about what the
|
|
51
|
+
// client offers - the worse half of a half-migration.
|
|
52
|
+
const isFederated = config.allowFederatedLogin !== false && config.providers.length > 0;
|
|
53
|
+
const isTraditional = config.allowTraditionalLogin !== false;
|
|
54
|
+
const totalLoading = isLoading || localLoading;
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<>
|
|
58
|
+
{error && (
|
|
59
|
+
<div
|
|
60
|
+
className="mb-6 px-4 py-3 rounded-lg"
|
|
61
|
+
style={{
|
|
62
|
+
background: 'var(--color-error, #ef4444)',
|
|
63
|
+
color: 'white',
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{error}
|
|
67
|
+
</div>
|
|
68
|
+
)}
|
|
69
|
+
|
|
70
|
+
{/* Federated Only Mode */}
|
|
71
|
+
{isFederated && (
|
|
72
|
+
<FederatedAuthSection
|
|
73
|
+
providers={config.providers}
|
|
74
|
+
onProviderClick={handleFederatedClick}
|
|
75
|
+
isLoading={totalLoading}
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
78
|
+
|
|
79
|
+
{/* Traditional Only Mode */}
|
|
80
|
+
{isTraditional && config.enableEmailSignup && (
|
|
81
|
+
<form onSubmit={handleTraditionalSubmit} className="space-y-4">
|
|
82
|
+
<div>
|
|
83
|
+
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
|
|
84
|
+
Email Address
|
|
85
|
+
</label>
|
|
86
|
+
<input
|
|
87
|
+
type="email"
|
|
88
|
+
value={email}
|
|
89
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
90
|
+
placeholder="you@example.com"
|
|
91
|
+
disabled={totalLoading}
|
|
92
|
+
required
|
|
93
|
+
className="w-full px-4 py-3 rounded-lg border transition-colors focus:outline-none focus:ring-2 disabled:opacity-50"
|
|
94
|
+
style={{
|
|
95
|
+
border: '1px solid var(--border-default)',
|
|
96
|
+
color: 'var(--text-primary)',
|
|
97
|
+
background: 'var(--bg-default)',
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div>
|
|
103
|
+
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
|
|
104
|
+
Password
|
|
105
|
+
</label>
|
|
106
|
+
<input
|
|
107
|
+
type="password"
|
|
108
|
+
value={password}
|
|
109
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
110
|
+
placeholder="••••••••"
|
|
111
|
+
disabled={totalLoading}
|
|
112
|
+
required
|
|
113
|
+
className="w-full px-4 py-3 rounded-lg border transition-colors focus:outline-none focus:ring-2 disabled:opacity-50"
|
|
114
|
+
style={{
|
|
115
|
+
border: '1px solid var(--border-default)',
|
|
116
|
+
color: 'var(--text-primary)',
|
|
117
|
+
background: 'var(--bg-default)',
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div>
|
|
123
|
+
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
|
|
124
|
+
Confirm Password
|
|
125
|
+
</label>
|
|
126
|
+
<input
|
|
127
|
+
type="password"
|
|
128
|
+
value={confirmPassword}
|
|
129
|
+
onChange={(e) => setConfirmPassword(e.target.value)}
|
|
130
|
+
placeholder="••••••••"
|
|
131
|
+
disabled={totalLoading}
|
|
132
|
+
required
|
|
133
|
+
className="w-full px-4 py-3 rounded-lg border transition-colors focus:outline-none focus:ring-2 disabled:opacity-50"
|
|
134
|
+
style={{
|
|
135
|
+
border: '1px solid var(--border-default)',
|
|
136
|
+
color: 'var(--text-primary)',
|
|
137
|
+
background: 'var(--bg-default)',
|
|
138
|
+
}}
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<button
|
|
143
|
+
type="submit"
|
|
144
|
+
disabled={totalLoading}
|
|
145
|
+
className="w-full py-3 px-4 rounded-lg font-semibold focus:outline-none focus:ring-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors mt-6"
|
|
146
|
+
style={{
|
|
147
|
+
border: '1px solid var(--border-default)',
|
|
148
|
+
color: 'white',
|
|
149
|
+
background: 'var(--color-primary, #10b981)',
|
|
150
|
+
}}
|
|
151
|
+
>
|
|
152
|
+
{totalLoading ? 'Creating Account...' : 'Create Account'}
|
|
153
|
+
</button>
|
|
154
|
+
</form>
|
|
155
|
+
)}
|
|
156
|
+
|
|
157
|
+
{/* PAY-2334: same three states as the login page. Not answered yet -> neutral text; read failed -> say so;
|
|
158
|
+
only an ANSWERED "nothing offered" falls through to the branch below. */}
|
|
159
|
+
{!isFederated && !isTraditional && config.settingsStatus === 'loading' && (
|
|
160
|
+
<div role="status" className="px-4 py-3 rounded-lg text-sm text-left" style={{ color: 'var(--text-secondary, #6b7280)' }}>
|
|
161
|
+
<p>Loading sign-up options…</p>
|
|
162
|
+
</div>
|
|
163
|
+
)}
|
|
164
|
+
|
|
165
|
+
{!isFederated && !isTraditional && config.settingsStatus === 'failed' && (
|
|
166
|
+
<div
|
|
167
|
+
role="alert"
|
|
168
|
+
className="px-4 py-3 rounded-lg text-sm text-left"
|
|
169
|
+
style={{
|
|
170
|
+
border: '1px solid var(--border-default, #e5e7eb)',
|
|
171
|
+
color: 'var(--text-primary, #111827)',
|
|
172
|
+
}}
|
|
173
|
+
>
|
|
174
|
+
<p className="font-semibold">Could not load sign-up options.</p>
|
|
175
|
+
<p className="mt-1">Please reload the page. If it keeps happening, contact an administrator.</p>
|
|
176
|
+
</div>
|
|
177
|
+
)}
|
|
178
|
+
|
|
179
|
+
{/* PAY-2341: ANSWERED, and nothing is offered. This branch used to be labelled "Hybrid Mode - Show both" and
|
|
180
|
+
rendered the federated section plus the email sign-up form on the same "neither" condition, so a client with no
|
|
181
|
+
sign-up method showed a working-looking form. Say so, as the login page does (ModeAwareLoginPage). */}
|
|
182
|
+
{!isFederated && !isTraditional && (config.settingsStatus ?? 'ready') === 'ready' && (
|
|
183
|
+
<div
|
|
184
|
+
role="alert"
|
|
185
|
+
className="px-4 py-3 rounded-lg text-sm text-left"
|
|
186
|
+
style={{
|
|
187
|
+
border: '1px solid var(--border-default, #e5e7eb)',
|
|
188
|
+
color: 'var(--text-primary, #111827)',
|
|
189
|
+
}}
|
|
190
|
+
>
|
|
191
|
+
<p className="font-semibold">Sign-up is not available for this application.</p>
|
|
192
|
+
<p className="mt-1">
|
|
193
|
+
No sign-up method is enabled for this client. An administrator needs to enable
|
|
194
|
+
a federated provider or username and password sign-in.
|
|
195
|
+
</p>
|
|
196
|
+
</div>
|
|
197
|
+
)}
|
|
198
|
+
</>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useEffect } from 'react';
|
|
4
|
-
import { passwordResetRedirect } from '../../auth/password-reset-bridge';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* PAY-2121: mount this once on your app's `/` page. When the IdP's post-verify
|
|
8
|
-
* redirect lands on `/#password_reset_required=true&reset_token=<t>&email=<e>`
|
|
9
|
-
* (a FRAGMENT), this performs ONE replace to the kit's reset surface and clears
|
|
10
|
-
* the hash. With any other fragment it renders nothing and leaves `/` alone.
|
|
11
|
-
*
|
|
12
|
-
* It renders nothing and reads no user data - it only inspects the fragment.
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* // app/page.tsx
|
|
16
|
-
* import { PasswordResetBridge } from '@payez/next-mvp/components/auth/PasswordResetBridge';
|
|
17
|
-
* export default function Home() {
|
|
18
|
-
* return (<><PasswordResetBridge /></>);
|
|
19
|
-
* }
|
|
20
|
-
*/
|
|
21
|
-
export function PasswordResetBridge() {
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
if (typeof window === 'undefined') return;
|
|
24
|
-
const target = passwordResetRedirect(window.location.hash);
|
|
25
|
-
if (target) window.location.replace(target);
|
|
26
|
-
}, []);
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default PasswordResetBridge;
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
import { passwordResetRedirect } from '../../auth/password-reset-bridge';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* PAY-2121: mount this once on your app's `/` page. When the IdP's post-verify
|
|
8
|
+
* redirect lands on `/#password_reset_required=true&reset_token=<t>&email=<e>`
|
|
9
|
+
* (a FRAGMENT), this performs ONE replace to the kit's reset surface and clears
|
|
10
|
+
* the hash. With any other fragment it renders nothing and leaves `/` alone.
|
|
11
|
+
*
|
|
12
|
+
* It renders nothing and reads no user data - it only inspects the fragment.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // app/page.tsx
|
|
16
|
+
* import { PasswordResetBridge } from '@payez/next-mvp/components/auth/PasswordResetBridge';
|
|
17
|
+
* export default function Home() {
|
|
18
|
+
* return (<><PasswordResetBridge /></>);
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
export function PasswordResetBridge() {
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (typeof window === 'undefined') return;
|
|
24
|
+
const target = passwordResetRedirect(window.location.hash);
|
|
25
|
+
if (target) window.location.replace(target);
|
|
26
|
+
}, []);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default PasswordResetBridge;
|