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
This commit is contained in:
@@ -278,7 +278,13 @@ export const buildFormState = async ({
|
||||
user: lockedDocument.docs[0]?.user?.value,
|
||||
}
|
||||
|
||||
if (updateLastEdited) {
|
||||
const lockOwnerId =
|
||||
typeof lockedDocument.docs[0]?.user?.value === 'object'
|
||||
? lockedDocument.docs[0]?.user?.value?.id
|
||||
: lockedDocument.docs[0]?.user?.value
|
||||
|
||||
// Should only update doc if the incoming / current user is also the owner of the locked doc
|
||||
if (updateLastEdited && req.user && lockOwnerId === req.user.id) {
|
||||
await req.payload.db.updateOne({
|
||||
id: lockedDocument.docs[0].id,
|
||||
collection: 'payload-locked-documents',
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
'use client'
|
||||
import type { TextFieldClientProps } from 'payload'
|
||||
|
||||
import { DatePicker, FieldLabel, useField } from '@payloadcms/ui'
|
||||
import { type FunctionComponent, useEffect, useRef } from 'react'
|
||||
|
||||
export const DocumentLoaded: FunctionComponent<TextFieldClientProps> = ({ field: label }) => {
|
||||
const field = useField<Date>({
|
||||
path: 'documentLoaded',
|
||||
})
|
||||
const hasRun = useRef(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (hasRun.current || field.formInitializing) {
|
||||
return
|
||||
}
|
||||
hasRun.current = true
|
||||
|
||||
field.setValue(new Date().toISOString())
|
||||
}, [field])
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
marginBottom: '20px',
|
||||
}}
|
||||
>
|
||||
<FieldLabel field={label} />
|
||||
<DatePicker displayFormat="yyyy-MM-dd hh:mm:ss" readOnly={true} value={field.value} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ export const PostsCollection: CollectionConfig = {
|
||||
slug: postsSlug,
|
||||
admin: {
|
||||
useAsTitle: 'text',
|
||||
defaultColumns: ['text', 'createdAt', 'updatedAt', '_status'],
|
||||
},
|
||||
lockDocuments: {
|
||||
duration: 180,
|
||||
@@ -15,6 +16,20 @@ export const PostsCollection: CollectionConfig = {
|
||||
name: 'text',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'documentLoaded',
|
||||
label: 'Document loaded',
|
||||
type: 'date',
|
||||
admin: {
|
||||
date: {
|
||||
displayFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
},
|
||||
readOnly: true,
|
||||
components: {
|
||||
Field: '/collections/Posts/fields/DocumentLoaded.tsx#DocumentLoaded',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
versions: {
|
||||
drafts: true,
|
||||
|
||||
Reference in New Issue
Block a user