Skip to content

Commit b14935c

Browse files
authored
fix(ui): unable to find user field schemas when updating password (#10305)
When updating password within the account view, the server console throws an error because it is unable to find the remaining user fields when building form state. This was because the field schema map sets these fields within its own `_users.auth` key, separate from the other fields. When the form submits, it uses this key as the schema path, which may not contain all user fields, even though it sends full document data through the request.
1 parent 2e58a4a commit b14935c

File tree

6 files changed

+17
-35
lines changed

6 files changed

+17
-35
lines changed

packages/next/src/views/CreateFirstUser/index.client.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const CreateFirstUserClient: React.FC<{
5757
docPreferences,
5858
formState: prevFormState,
5959
operation: 'create',
60-
schemaPath: `_${userSlug}.auth`,
60+
schemaPath: userSlug,
6161
signal: controller.signal,
6262
})
6363

packages/ui/src/utilities/buildClientFieldSchemaMap/index.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,22 @@ export const buildClientFieldSchemaMap = (args: {
4444
)
4545

4646
if (matchedCollection) {
47+
let fieldsToSet = matchedCollection?.fields || []
48+
4749
if (matchedCollection.auth && !matchedCollection.auth.disableLocalStrategy) {
48-
// register schema with auth schemaPath
4950
;(baseAuthFields[0] as TextFieldClient).label = i18n.t('general:password')
5051
;(baseAuthFields[1] as TextFieldClient).label = i18n.t('authentication:confirmPassword')
51-
52-
clientSchemaMap.set(`_${matchedCollection.slug}.auth`, {
53-
fields: [...baseAuthFields, ...matchedCollection.fields],
54-
})
52+
fieldsToSet = baseAuthFields.concat(fieldsToSet)
5553
}
5654

5755
clientSchemaMap.set(collectionSlug, {
58-
fields: matchedCollection.fields,
56+
fields: fieldsToSet,
5957
})
6058

6159
traverseFields({
6260
clientSchemaMap,
6361
config,
64-
fields: matchedCollection.fields,
62+
fields: fieldsToSet,
6563
i18n,
6664
parentIndexPath: '',
6765
parentSchemaPath: collectionSlug,

packages/ui/src/utilities/buildFieldSchemaMap/index.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,21 @@ export const buildFieldSchemaMap = (args: {
3939
)
4040

4141
if (matchedCollection) {
42+
let fieldsToSet = matchedCollection?.fields || []
43+
4244
if (matchedCollection.auth && !matchedCollection.auth.disableLocalStrategy) {
43-
// register schema with auth schemaPath
4445
;(baseAuthFields[0] as TextField).label = i18n.t('general:password')
4546
;(baseAuthFields[1] as TextField).label = i18n.t('authentication:confirmPassword')
46-
47-
schemaMap.set(`_${matchedCollection.slug}.auth`, {
48-
fields: [...baseAuthFields, ...matchedCollection.fields],
49-
})
47+
fieldsToSet = baseAuthFields.concat(fieldsToSet)
5048
}
5149

5250
schemaMap.set(collectionSlug, {
53-
fields: matchedCollection.fields,
51+
fields: fieldsToSet,
5452
})
5553

5654
traverseFields({
5755
config,
58-
fields: matchedCollection.fields,
56+
fields: fieldsToSet,
5957
i18n,
6058
parentIndexPath: '',
6159
parentSchemaPath: collectionSlug,

packages/ui/src/views/Edit/Auth/index.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export const Auth: React.FC<Props> = (props) => {
3030
operation,
3131
readOnly,
3232
requirePassword,
33-
setSchemaPathSegments,
3433
setValidateBeforeSubmit,
3534
useAPIKey,
3635
username,
@@ -40,7 +39,6 @@ export const Auth: React.FC<Props> = (props) => {
4039
const { permissions } = useAuth()
4140
const [changingPassword, setChangingPassword] = useState(requirePassword)
4241
const enableAPIKey = useFormFields(([fields]) => (fields && fields?.enableAPIKey) || null)
43-
const forceOpenChangePassword = useFormFields(([fields]) => (fields && fields?.password) || null)
4442
const dispatchFields = useFormFields((reducer) => reducer[1])
4543
const modified = useFormModified()
4644
const { i18n, t } = useTranslation()
@@ -81,7 +79,6 @@ export const Auth: React.FC<Props> = (props) => {
8179
(showPasswordFields: boolean) => {
8280
if (showPasswordFields) {
8381
setValidateBeforeSubmit(true)
84-
setSchemaPathSegments([`_${collectionSlug}`, 'auth'])
8582

8683
dispatchFields({
8784
type: 'UPDATE',
@@ -98,14 +95,13 @@ export const Auth: React.FC<Props> = (props) => {
9895
})
9996
} else {
10097
setValidateBeforeSubmit(false)
101-
setSchemaPathSegments([collectionSlug])
10298
dispatchFields({ type: 'REMOVE', path: 'password' })
10399
dispatchFields({ type: 'REMOVE', path: 'confirm-password' })
104100
}
105101

106102
setChangingPassword(showPasswordFields)
107103
},
108-
[dispatchFields, t, collectionSlug, setSchemaPathSegments, setValidateBeforeSubmit],
104+
[dispatchFields, t, setValidateBeforeSubmit],
109105
)
110106

111107
const unlock = useCallback(async () => {
@@ -140,8 +136,6 @@ export const Auth: React.FC<Props> = (props) => {
140136

141137
const disabled = readOnly || isInitializing
142138

143-
const showPasswordFields = changingPassword || forceOpenChangePassword
144-
145139
return (
146140
<div className={[baseClass, className].filter(Boolean).join(' ')}>
147141
{!disableLocalStrategy && (
@@ -153,7 +147,7 @@ export const Auth: React.FC<Props> = (props) => {
153147
readOnly={readOnly}
154148
t={t}
155149
/>
156-
{(showPasswordFields || requirePassword) && (
150+
{(changingPassword || requirePassword) && (
157151
<div className={`${baseClass}__changing-password`}>
158152
<PasswordField
159153
autoComplete="new-password"
@@ -172,7 +166,7 @@ export const Auth: React.FC<Props> = (props) => {
172166
</div>
173167
)}
174168
<div className={`${baseClass}__controls`}>
175-
{showPasswordFields && !requirePassword && (
169+
{changingPassword && !requirePassword && (
176170
<Button
177171
buttonStyle="secondary"
178172
disabled={disabled}
@@ -182,7 +176,7 @@ export const Auth: React.FC<Props> = (props) => {
182176
{t('general:cancel')}
183177
</Button>
184178
)}
185-
{!showPasswordFields && !requirePassword && (
179+
{!changingPassword && !requirePassword && (
186180
<Button
187181
buttonStyle="secondary"
188182
disabled={disabled}

packages/ui/src/views/Edit/Auth/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ export type Props = {
99
operation: 'create' | 'update'
1010
readOnly: boolean
1111
requirePassword?: boolean
12-
setSchemaPathSegments: (path: string[]) => void
1312
setValidateBeforeSubmit: (validate: boolean) => void
1413
useAPIKey?: boolean
1514
username: string

packages/ui/src/views/Edit/index.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
} from 'payload'
1010

1111
import { useRouter, useSearchParams } from 'next/navigation.js'
12-
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
12+
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'
1313

1414
import type { FormProps } from '../../forms/Form/index.js'
1515
import type { LockedState } from '../../utilities/buildFormState.js'
@@ -179,13 +179,7 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
179179
classes.push(`collection-edit--${collectionSlug}`)
180180
}
181181

182-
const [schemaPathSegments, setSchemaPathSegments] = useState(() => {
183-
if (operation === 'create' && auth && !auth.disableLocalStrategy) {
184-
return [`_${entitySlug}`, 'auth']
185-
}
186-
187-
return [entitySlug]
188-
})
182+
const schemaPathSegments = useMemo(() => [entitySlug], [entitySlug])
189183

190184
const [validateBeforeSubmit, setValidateBeforeSubmit] = useState(() => {
191185
if (operation === 'create' && auth && !auth.disableLocalStrategy) {
@@ -557,7 +551,6 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
557551
operation={operation}
558552
readOnly={!hasSavePermission}
559553
requirePassword={!id}
560-
setSchemaPathSegments={setSchemaPathSegments}
561554
setValidateBeforeSubmit={setValidateBeforeSubmit}
562555
useAPIKey={auth.useAPIKey}
563556
username={savedDocumentData?.username}

0 commit comments

Comments
 (0)