@delmaredigital/payload-better-auth 0.3.8 → 0.3.9
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/package.json +34 -91
- package/src/adapter/collections.ts +0 -621
- package/src/adapter/index.ts +0 -712
- package/src/components/BeforeLogin.tsx +0 -39
- package/src/components/LoginView.tsx +0 -1516
- package/src/components/LoginViewWrapper.tsx +0 -35
- package/src/components/LogoutButton.tsx +0 -58
- package/src/components/PasskeyRegisterButton.tsx +0 -105
- package/src/components/PasskeySignInButton.tsx +0 -96
- package/src/components/auth/ForgotPasswordView.tsx +0 -274
- package/src/components/auth/ResetPasswordView.tsx +0 -331
- package/src/components/auth/index.ts +0 -8
- package/src/components/management/ApiKeysManagementClient.tsx +0 -988
- package/src/components/management/PasskeysManagementClient.tsx +0 -409
- package/src/components/management/SecurityNavLinks.tsx +0 -117
- package/src/components/management/TwoFactorManagementClient.tsx +0 -560
- package/src/components/management/index.ts +0 -20
- package/src/components/management/views/ApiKeysView.tsx +0 -57
- package/src/components/management/views/PasskeysView.tsx +0 -42
- package/src/components/management/views/TwoFactorView.tsx +0 -42
- package/src/components/management/views/index.ts +0 -10
- package/src/components/twoFactor/TwoFactorSetupView.tsx +0 -515
- package/src/components/twoFactor/TwoFactorVerifyView.tsx +0 -238
- package/src/components/twoFactor/index.ts +0 -8
- package/src/exports/client.ts +0 -77
- package/src/exports/components.ts +0 -30
- package/src/exports/management.ts +0 -25
- package/src/exports/rsc.ts +0 -11
- package/src/generated-types.ts +0 -269
- package/src/index.ts +0 -135
- package/src/plugin/index.ts +0 -834
- package/src/scripts/generate-types.ts +0 -269
- package/src/types/apiKey.ts +0 -63
- package/src/types/betterAuth.ts +0 -253
- package/src/utils/access.ts +0 -410
- package/src/utils/apiKeyAccess.ts +0 -443
- package/src/utils/betterAuthDefaults.ts +0 -102
- package/src/utils/detectAuthConfig.ts +0 -47
- package/src/utils/detectEnabledPlugins.ts +0 -69
- package/src/utils/firstUserAdmin.ts +0 -164
- package/src/utils/generateScopes.ts +0 -150
- package/src/utils/session.ts +0 -91
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useState, useEffect, type FormEvent } from 'react'
|
|
4
|
-
import { useRouter, useSearchParams } from 'next/navigation.js'
|
|
5
|
-
|
|
6
|
-
export type ResetPasswordViewProps = {
|
|
7
|
-
/** Custom logo element */
|
|
8
|
-
logo?: React.ReactNode
|
|
9
|
-
/** Page title. Default: 'Reset Password' */
|
|
10
|
-
title?: string
|
|
11
|
-
/** Path to redirect after successful reset. Default: '/admin/login' */
|
|
12
|
-
afterResetPath?: string
|
|
13
|
-
/** Minimum password length. Default: 8 */
|
|
14
|
-
minPasswordLength?: number
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Reset password page component for setting a new password.
|
|
19
|
-
* Expects a token in the URL query parameter.
|
|
20
|
-
* Uses Better Auth's resetPassword endpoint.
|
|
21
|
-
*/
|
|
22
|
-
export function ResetPasswordView({
|
|
23
|
-
logo,
|
|
24
|
-
title = 'Reset Password',
|
|
25
|
-
afterResetPath = '/admin/login',
|
|
26
|
-
minPasswordLength = 8,
|
|
27
|
-
}: ResetPasswordViewProps) {
|
|
28
|
-
const router = useRouter()
|
|
29
|
-
const searchParams = useSearchParams()
|
|
30
|
-
const [password, setPassword] = useState('')
|
|
31
|
-
const [confirmPassword, setConfirmPassword] = useState('')
|
|
32
|
-
const [error, setError] = useState<string | null>(null)
|
|
33
|
-
const [success, setSuccess] = useState(false)
|
|
34
|
-
const [loading, setLoading] = useState(false)
|
|
35
|
-
const [token, setToken] = useState<string | null>(null)
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
const tokenParam = searchParams.get('token')
|
|
39
|
-
if (!tokenParam) {
|
|
40
|
-
setError('Invalid or missing reset token. Please request a new password reset link.')
|
|
41
|
-
} else {
|
|
42
|
-
setToken(tokenParam)
|
|
43
|
-
}
|
|
44
|
-
}, [searchParams])
|
|
45
|
-
|
|
46
|
-
async function handleSubmit(e: FormEvent) {
|
|
47
|
-
e.preventDefault()
|
|
48
|
-
setError(null)
|
|
49
|
-
|
|
50
|
-
if (password.length < minPasswordLength) {
|
|
51
|
-
setError(`Password must be at least ${minPasswordLength} characters.`)
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (password !== confirmPassword) {
|
|
56
|
-
setError('Passwords do not match.')
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (!token) {
|
|
61
|
-
setError('Invalid reset token.')
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
setLoading(true)
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
const response = await fetch('/api/auth/reset-password', {
|
|
69
|
-
method: 'POST',
|
|
70
|
-
headers: { 'Content-Type': 'application/json' },
|
|
71
|
-
credentials: 'include',
|
|
72
|
-
body: JSON.stringify({
|
|
73
|
-
token,
|
|
74
|
-
newPassword: password,
|
|
75
|
-
}),
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
if (response.ok) {
|
|
79
|
-
setSuccess(true)
|
|
80
|
-
} else {
|
|
81
|
-
const data = await response.json().catch(() => ({}))
|
|
82
|
-
setError(data.message || data.error?.message || 'Failed to reset password. The link may have expired.')
|
|
83
|
-
}
|
|
84
|
-
} catch {
|
|
85
|
-
setError('An error occurred. Please try again.')
|
|
86
|
-
} finally {
|
|
87
|
-
setLoading(false)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (success) {
|
|
92
|
-
return (
|
|
93
|
-
<div
|
|
94
|
-
style={{
|
|
95
|
-
minHeight: '100vh',
|
|
96
|
-
display: 'flex',
|
|
97
|
-
alignItems: 'center',
|
|
98
|
-
justifyContent: 'center',
|
|
99
|
-
background: 'var(--theme-bg)',
|
|
100
|
-
padding: 'var(--base)',
|
|
101
|
-
}}
|
|
102
|
-
>
|
|
103
|
-
<div
|
|
104
|
-
style={{
|
|
105
|
-
background: 'var(--theme-elevation-50)',
|
|
106
|
-
padding: 'calc(var(--base) * 2)',
|
|
107
|
-
borderRadius: 'var(--style-radius-m)',
|
|
108
|
-
boxShadow: '0 2px 20px rgba(0, 0, 0, 0.1)',
|
|
109
|
-
width: '100%',
|
|
110
|
-
maxWidth: '400px',
|
|
111
|
-
textAlign: 'center',
|
|
112
|
-
}}
|
|
113
|
-
>
|
|
114
|
-
{logo && (
|
|
115
|
-
<div style={{ marginBottom: 'calc(var(--base) * 1.5)' }}>
|
|
116
|
-
{logo}
|
|
117
|
-
</div>
|
|
118
|
-
)}
|
|
119
|
-
|
|
120
|
-
<h1
|
|
121
|
-
style={{
|
|
122
|
-
color: 'var(--theme-success-500)',
|
|
123
|
-
fontSize: 'var(--font-size-h3)',
|
|
124
|
-
fontWeight: 600,
|
|
125
|
-
margin: '0 0 var(--base) 0',
|
|
126
|
-
}}
|
|
127
|
-
>
|
|
128
|
-
Password Reset!
|
|
129
|
-
</h1>
|
|
130
|
-
|
|
131
|
-
<p
|
|
132
|
-
style={{
|
|
133
|
-
color: 'var(--theme-text)',
|
|
134
|
-
opacity: 0.8,
|
|
135
|
-
marginBottom: 'calc(var(--base) * 1.5)',
|
|
136
|
-
fontSize: 'var(--font-size-small)',
|
|
137
|
-
}}
|
|
138
|
-
>
|
|
139
|
-
Your password has been successfully reset. You can now log in with your new password.
|
|
140
|
-
</p>
|
|
141
|
-
|
|
142
|
-
<button
|
|
143
|
-
onClick={() => router.push(afterResetPath)}
|
|
144
|
-
style={{
|
|
145
|
-
padding: 'calc(var(--base) * 0.75) calc(var(--base) * 1.5)',
|
|
146
|
-
background: 'var(--theme-elevation-800)',
|
|
147
|
-
border: 'none',
|
|
148
|
-
borderRadius: 'var(--style-radius-s)',
|
|
149
|
-
color: 'var(--theme-elevation-50)',
|
|
150
|
-
fontSize: 'var(--font-size-base)',
|
|
151
|
-
fontWeight: 500,
|
|
152
|
-
cursor: 'pointer',
|
|
153
|
-
}}
|
|
154
|
-
>
|
|
155
|
-
Go to Login
|
|
156
|
-
</button>
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
|
159
|
-
)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return (
|
|
163
|
-
<div
|
|
164
|
-
style={{
|
|
165
|
-
minHeight: '100vh',
|
|
166
|
-
display: 'flex',
|
|
167
|
-
alignItems: 'center',
|
|
168
|
-
justifyContent: 'center',
|
|
169
|
-
background: 'var(--theme-bg)',
|
|
170
|
-
padding: 'var(--base)',
|
|
171
|
-
}}
|
|
172
|
-
>
|
|
173
|
-
<div
|
|
174
|
-
style={{
|
|
175
|
-
background: 'var(--theme-elevation-50)',
|
|
176
|
-
padding: 'calc(var(--base) * 2)',
|
|
177
|
-
borderRadius: 'var(--style-radius-m)',
|
|
178
|
-
boxShadow: '0 2px 20px rgba(0, 0, 0, 0.1)',
|
|
179
|
-
width: '100%',
|
|
180
|
-
maxWidth: '400px',
|
|
181
|
-
}}
|
|
182
|
-
>
|
|
183
|
-
{logo && (
|
|
184
|
-
<div
|
|
185
|
-
style={{
|
|
186
|
-
textAlign: 'center',
|
|
187
|
-
marginBottom: 'calc(var(--base) * 1.5)',
|
|
188
|
-
}}
|
|
189
|
-
>
|
|
190
|
-
{logo}
|
|
191
|
-
</div>
|
|
192
|
-
)}
|
|
193
|
-
|
|
194
|
-
<h1
|
|
195
|
-
style={{
|
|
196
|
-
color: 'var(--theme-text)',
|
|
197
|
-
fontSize: 'var(--font-size-h3)',
|
|
198
|
-
fontWeight: 600,
|
|
199
|
-
marginBottom: 'calc(var(--base) * 0.5)',
|
|
200
|
-
textAlign: 'center',
|
|
201
|
-
margin: '0 0 calc(var(--base) * 0.5) 0',
|
|
202
|
-
}}
|
|
203
|
-
>
|
|
204
|
-
{title}
|
|
205
|
-
</h1>
|
|
206
|
-
|
|
207
|
-
<p
|
|
208
|
-
style={{
|
|
209
|
-
color: 'var(--theme-text)',
|
|
210
|
-
opacity: 0.7,
|
|
211
|
-
fontSize: 'var(--font-size-small)',
|
|
212
|
-
textAlign: 'center',
|
|
213
|
-
marginBottom: 'calc(var(--base) * 1.5)',
|
|
214
|
-
}}
|
|
215
|
-
>
|
|
216
|
-
Enter your new password below.
|
|
217
|
-
</p>
|
|
218
|
-
|
|
219
|
-
<form onSubmit={handleSubmit}>
|
|
220
|
-
<div style={{ marginBottom: 'var(--base)' }}>
|
|
221
|
-
<label
|
|
222
|
-
htmlFor="password"
|
|
223
|
-
style={{
|
|
224
|
-
display: 'block',
|
|
225
|
-
color: 'var(--theme-text)',
|
|
226
|
-
marginBottom: 'calc(var(--base) * 0.5)',
|
|
227
|
-
fontSize: 'var(--font-size-small)',
|
|
228
|
-
fontWeight: 500,
|
|
229
|
-
}}
|
|
230
|
-
>
|
|
231
|
-
New Password
|
|
232
|
-
</label>
|
|
233
|
-
<input
|
|
234
|
-
id="password"
|
|
235
|
-
type="password"
|
|
236
|
-
value={password}
|
|
237
|
-
onChange={(e) => setPassword(e.target.value)}
|
|
238
|
-
required
|
|
239
|
-
minLength={minPasswordLength}
|
|
240
|
-
autoComplete="new-password"
|
|
241
|
-
style={{
|
|
242
|
-
width: '100%',
|
|
243
|
-
padding: 'calc(var(--base) * 0.75)',
|
|
244
|
-
background: 'var(--theme-input-bg)',
|
|
245
|
-
border: '1px solid var(--theme-elevation-150)',
|
|
246
|
-
borderRadius: 'var(--style-radius-s)',
|
|
247
|
-
color: 'var(--theme-text)',
|
|
248
|
-
fontSize: 'var(--font-size-base)',
|
|
249
|
-
outline: 'none',
|
|
250
|
-
boxSizing: 'border-box',
|
|
251
|
-
}}
|
|
252
|
-
/>
|
|
253
|
-
</div>
|
|
254
|
-
|
|
255
|
-
<div style={{ marginBottom: 'calc(var(--base) * 1.5)' }}>
|
|
256
|
-
<label
|
|
257
|
-
htmlFor="confirmPassword"
|
|
258
|
-
style={{
|
|
259
|
-
display: 'block',
|
|
260
|
-
color: 'var(--theme-text)',
|
|
261
|
-
marginBottom: 'calc(var(--base) * 0.5)',
|
|
262
|
-
fontSize: 'var(--font-size-small)',
|
|
263
|
-
fontWeight: 500,
|
|
264
|
-
}}
|
|
265
|
-
>
|
|
266
|
-
Confirm Password
|
|
267
|
-
</label>
|
|
268
|
-
<input
|
|
269
|
-
id="confirmPassword"
|
|
270
|
-
type="password"
|
|
271
|
-
value={confirmPassword}
|
|
272
|
-
onChange={(e) => setConfirmPassword(e.target.value)}
|
|
273
|
-
required
|
|
274
|
-
minLength={minPasswordLength}
|
|
275
|
-
autoComplete="new-password"
|
|
276
|
-
style={{
|
|
277
|
-
width: '100%',
|
|
278
|
-
padding: 'calc(var(--base) * 0.75)',
|
|
279
|
-
background: 'var(--theme-input-bg)',
|
|
280
|
-
border: '1px solid var(--theme-elevation-150)',
|
|
281
|
-
borderRadius: 'var(--style-radius-s)',
|
|
282
|
-
color: 'var(--theme-text)',
|
|
283
|
-
fontSize: 'var(--font-size-base)',
|
|
284
|
-
outline: 'none',
|
|
285
|
-
boxSizing: 'border-box',
|
|
286
|
-
}}
|
|
287
|
-
/>
|
|
288
|
-
</div>
|
|
289
|
-
|
|
290
|
-
{error && (
|
|
291
|
-
<div
|
|
292
|
-
style={{
|
|
293
|
-
color: 'var(--theme-error-500)',
|
|
294
|
-
marginBottom: 'var(--base)',
|
|
295
|
-
fontSize: 'var(--font-size-small)',
|
|
296
|
-
padding: 'calc(var(--base) * 0.5)',
|
|
297
|
-
background: 'var(--theme-error-50)',
|
|
298
|
-
borderRadius: 'var(--style-radius-s)',
|
|
299
|
-
border: '1px solid var(--theme-error-200)',
|
|
300
|
-
}}
|
|
301
|
-
>
|
|
302
|
-
{error}
|
|
303
|
-
</div>
|
|
304
|
-
)}
|
|
305
|
-
|
|
306
|
-
<button
|
|
307
|
-
type="submit"
|
|
308
|
-
disabled={loading || !token}
|
|
309
|
-
style={{
|
|
310
|
-
width: '100%',
|
|
311
|
-
padding: 'calc(var(--base) * 0.75)',
|
|
312
|
-
background: 'var(--theme-elevation-800)',
|
|
313
|
-
border: 'none',
|
|
314
|
-
borderRadius: 'var(--style-radius-s)',
|
|
315
|
-
color: 'var(--theme-elevation-50)',
|
|
316
|
-
fontSize: 'var(--font-size-base)',
|
|
317
|
-
fontWeight: 500,
|
|
318
|
-
cursor: loading || !token ? 'not-allowed' : 'pointer',
|
|
319
|
-
opacity: loading || !token ? 0.7 : 1,
|
|
320
|
-
transition: 'opacity 150ms ease',
|
|
321
|
-
}}
|
|
322
|
-
>
|
|
323
|
-
{loading ? 'Resetting...' : 'Reset Password'}
|
|
324
|
-
</button>
|
|
325
|
-
</form>
|
|
326
|
-
</div>
|
|
327
|
-
</div>
|
|
328
|
-
)
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
export default ResetPasswordView
|