Skip to content

Commit ebd3c02

Browse files
authored
fix(ui): updatedAt field in locked-docs collection able to be updated by non-owner (#9026)
### What? If you have a custom field that sets the value of the field using the `useField` hook on entry into a document - the `updatedAt` field would be updated even when a non-owner tries to enter a locked document. ### Why? When a field is updated in the edit view - we perform an update in `form-state` to keep the doc in `payload-locked-documents` up to date with the current editing status. The above scenario would hit this update operation even on non-owner users because it was previously only checking for `updateLastEdited` (which would get hit by the `setValue` in the `useField` hook) so we also need to check to make sure the current user entering a locked doc is also the owner of the document. ### How? When performing an update to `payload-locked-documents` in `buildFormState` - only perform the update if the current user is also the owner of the locked document otherwise skip the `update` operation. Fixes #8781
1 parent ddc9d97 commit ebd3c02

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

packages/ui/src/utilities/buildFormState.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,13 @@ export const buildFormState = async ({
278278
user: lockedDocument.docs[0]?.user?.value,
279279
}
280280

281-
if (updateLastEdited) {
281+
const lockOwnerId =
282+
typeof lockedDocument.docs[0]?.user?.value === 'object'
283+
? lockedDocument.docs[0]?.user?.value?.id
284+
: lockedDocument.docs[0]?.user?.value
285+
286+
// Should only update doc if the incoming / current user is also the owner of the locked doc
287+
if (updateLastEdited && req.user && lockOwnerId === req.user.id) {
282288
await req.payload.db.updateOne({
283289
id: lockedDocument.docs[0].id,
284290
collection: 'payload-locked-documents',
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use client'
2+
import type { TextFieldClientProps } from 'payload'
3+
4+
import { DatePicker, FieldLabel, useField } from '@payloadcms/ui'
5+
import { type FunctionComponent, useEffect, useRef } from 'react'
6+
7+
export const DocumentLoaded: FunctionComponent<TextFieldClientProps> = ({ field: label }) => {
8+
const field = useField<Date>({
9+
path: 'documentLoaded',
10+
})
11+
const hasRun = useRef(false)
12+
13+
useEffect(() => {
14+
if (hasRun.current || field.formInitializing) {
15+
return
16+
}
17+
hasRun.current = true
18+
19+
field.setValue(new Date().toISOString())
20+
}, [field])
21+
22+
return (
23+
<div
24+
style={{
25+
marginBottom: '20px',
26+
}}
27+
>
28+
<FieldLabel field={label} />
29+
<DatePicker displayFormat="yyyy-MM-dd hh:mm:ss" readOnly={true} value={field.value} />
30+
</div>
31+
)
32+
}

test/locked-documents/collections/Posts/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const PostsCollection: CollectionConfig = {
66
slug: postsSlug,
77
admin: {
88
useAsTitle: 'text',
9+
defaultColumns: ['text', 'createdAt', 'updatedAt', '_status'],
910
},
1011
lockDocuments: {
1112
duration: 180,
@@ -15,6 +16,20 @@ export const PostsCollection: CollectionConfig = {
1516
name: 'text',
1617
type: 'text',
1718
},
19+
{
20+
name: 'documentLoaded',
21+
label: 'Document loaded',
22+
type: 'date',
23+
admin: {
24+
date: {
25+
displayFormat: 'yyyy-MM-dd HH:mm:ss',
26+
},
27+
readOnly: true,
28+
components: {
29+
Field: '/collections/Posts/fields/DocumentLoaded.tsx#DocumentLoaded',
30+
},
31+
},
32+
},
1833
],
1934
versions: {
2035
drafts: true,

0 commit comments

Comments
 (0)