chore: cleans up locked-documents (#8269)
Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
This commit is contained in:
@@ -16,7 +16,7 @@ import './index.scss'
|
||||
const baseClass = 'dashboard'
|
||||
|
||||
export type DashboardProps = {
|
||||
globalData: Array<{ data: { isLocked: boolean; userEditing: ClientUser | null }; slug: string }>
|
||||
globalData: Array<{ data: { _isLocked: boolean; _userEditing: ClientUser | null }; slug: string }>
|
||||
Link: React.ComponentType<any>
|
||||
navGroups?: ReturnType<typeof groupNavItems>
|
||||
permissions: Permissions
|
||||
@@ -131,8 +131,8 @@ export const DefaultDashboard: React.FC<DashboardProps> = (props) => {
|
||||
(global) => global.slug === entity.slug,
|
||||
)
|
||||
if (globalLockData) {
|
||||
lockStatus = globalLockData.data.isLocked
|
||||
userEditing = globalLockData.data.userEditing
|
||||
lockStatus = globalLockData.data._isLocked
|
||||
userEditing = globalLockData.data._userEditing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ export const deleteOperation = async <TSlug extends CollectionSlug>(
|
||||
// Handle potentially locked documents
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { lockedDocument, shouldUnlockDocument } = await checkDocumentLockStatus({
|
||||
await checkDocumentLockStatus({
|
||||
id,
|
||||
collectionSlug: collectionConfig.slug,
|
||||
lockErrorMessage: `Document with ID ${id} is currently locked and cannot be deleted.`,
|
||||
@@ -152,20 +152,6 @@ export const deleteOperation = async <TSlug extends CollectionSlug>(
|
||||
req,
|
||||
})
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Unlock the document if necessary
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (shouldUnlockDocument && lockedDocument) {
|
||||
await payload.db.deleteOne({
|
||||
collection: 'payload-locked-documents',
|
||||
req,
|
||||
where: {
|
||||
id: { equals: lockedDocument.id },
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete versions
|
||||
// /////////////////////////////////////
|
||||
|
||||
@@ -114,7 +114,7 @@ export const deleteByIDOperation = async <TSlug extends CollectionSlug>(
|
||||
// Handle potentially locked documents
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { lockedDocument, shouldUnlockDocument } = await checkDocumentLockStatus({
|
||||
await checkDocumentLockStatus({
|
||||
id,
|
||||
collectionSlug: collectionConfig.slug,
|
||||
lockErrorMessage: `Document with ID ${id} is currently locked and cannot be deleted.`,
|
||||
@@ -129,20 +129,6 @@ export const deleteByIDOperation = async <TSlug extends CollectionSlug>(
|
||||
req,
|
||||
})
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Unlock the document if necessary
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (shouldUnlockDocument && lockedDocument) {
|
||||
await payload.db.deleteOne({
|
||||
collection: 'payload-locked-documents',
|
||||
req,
|
||||
where: {
|
||||
id: { equals: lockedDocument.id },
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete versions
|
||||
// /////////////////////////////////////
|
||||
|
||||
@@ -182,15 +182,15 @@ export const findOperation = async <TSlug extends CollectionSlug>(
|
||||
const lockedDoc = lockedDocs.find((lock) => lock?.document?.value === doc.id)
|
||||
return {
|
||||
...doc,
|
||||
isLocked: !!lockedDoc,
|
||||
userEditing: lockedDoc ? lockedDoc._lastEdited?.user?.value : null,
|
||||
_isLocked: !!lockedDoc,
|
||||
_userEditing: lockedDoc ? lockedDoc?.user?.value : null,
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
result.docs = result.docs.map((doc) => ({
|
||||
...doc,
|
||||
isLocked: false,
|
||||
userEditing: null,
|
||||
_isLocked: false,
|
||||
_userEditing: null,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ export const findByIDOperation = async <TSlug extends CollectionSlug>(
|
||||
// swallow error
|
||||
}
|
||||
|
||||
result.isLocked = !!lockStatus
|
||||
result.userEditing = lockStatus?._lastEdited?.user?.value ?? null
|
||||
result._isLocked = !!lockStatus
|
||||
result._userEditing = lockStatus?.user?.value ?? null
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
|
||||
@@ -182,7 +182,7 @@ export const updateOperation = async <TSlug extends CollectionSlug>(
|
||||
// Handle potentially locked documents
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { lockedDocument, shouldUnlockDocument } = await checkDocumentLockStatus({
|
||||
await checkDocumentLockStatus({
|
||||
id,
|
||||
collectionSlug: collectionConfig.slug,
|
||||
lockErrorMessage: `Document with ID ${id} is currently locked by another user and cannot be updated.`,
|
||||
@@ -335,20 +335,6 @@ export const updateOperation = async <TSlug extends CollectionSlug>(
|
||||
})
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Unlock the document if necessary
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (shouldUnlockDocument && lockedDocument) {
|
||||
await payload.db.deleteOne({
|
||||
collection: 'payload-locked-documents',
|
||||
req,
|
||||
where: {
|
||||
id: { equals: lockedDocument.id },
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
@@ -146,7 +146,7 @@ export const updateByIDOperation = async <TSlug extends CollectionSlug>(
|
||||
// Handle potentially locked documents
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { lockedDocument, shouldUnlockDocument } = await checkDocumentLockStatus({
|
||||
await checkDocumentLockStatus({
|
||||
id,
|
||||
collectionSlug: collectionConfig.slug,
|
||||
lockErrorMessage: `Document with ID ${id} is currently locked by another user and cannot be updated.`,
|
||||
@@ -365,20 +365,6 @@ export const updateByIDOperation = async <TSlug extends CollectionSlug>(
|
||||
})
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Unlock the document if necessary
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (shouldUnlockDocument && lockedDocument) {
|
||||
await payload.db.deleteOne({
|
||||
collection: 'payload-locked-documents',
|
||||
req,
|
||||
where: {
|
||||
id: { equals: lockedDocument.id },
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
@@ -86,8 +86,8 @@ export const findOneOperation = async <T extends Record<string, unknown>>(
|
||||
// swallow error
|
||||
}
|
||||
|
||||
doc.isLocked = !!lockStatus
|
||||
doc.userEditing = lockStatus?._lastEdited?.user?.value ?? null
|
||||
doc._isLocked = !!lockStatus
|
||||
doc._userEditing = lockStatus?.user?.value ?? null
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
|
||||
@@ -5,7 +5,6 @@ import type { Operation, PayloadRequest, Where } from '../../types/index.js'
|
||||
import type { DataFromGlobalSlug, SanitizedGlobalConfig } from '../config/types.js'
|
||||
|
||||
import executeAccess from '../../auth/executeAccess.js'
|
||||
import { APIError } from '../../errors/index.js'
|
||||
import { afterChange } from '../../fields/hooks/afterChange/index.js'
|
||||
import { afterRead } from '../../fields/hooks/afterRead/index.js'
|
||||
import { beforeChange } from '../../fields/hooks/beforeChange/index.js'
|
||||
@@ -119,7 +118,7 @@ export const updateOperation = async <TSlug extends GlobalSlug>(
|
||||
// Handle potentially locked global documents
|
||||
// ///////////////////////////////////////////
|
||||
|
||||
const { lockedDocument, shouldUnlockDocument } = await checkDocumentLockStatus({
|
||||
await checkDocumentLockStatus({
|
||||
globalSlug: slug,
|
||||
lockErrorMessage: `Global with slug "${slug}" is currently locked by another user and cannot be updated.`,
|
||||
req,
|
||||
@@ -262,22 +261,6 @@ export const updateOperation = async <TSlug extends GlobalSlug>(
|
||||
}
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Unlock the global if necessary
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (shouldUnlockDocument && lockedDocument) {
|
||||
await payload.db.deleteOne({
|
||||
collection: 'payload-locked-documents',
|
||||
req,
|
||||
where: {
|
||||
globalSlug: {
|
||||
equals: slug,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
@@ -14,32 +14,21 @@ export const getLockedDocumentsCollection = (config: Config): CollectionConfig =
|
||||
maxDepth: 0,
|
||||
relationTo: [...config.collections.map((collectionConfig) => collectionConfig.slug)],
|
||||
},
|
||||
{
|
||||
name: 'editedAt',
|
||||
type: 'date',
|
||||
},
|
||||
{
|
||||
name: 'globalSlug',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: '_lastEdited',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
name: 'user',
|
||||
type: 'relationship',
|
||||
relationTo: config.collections
|
||||
.filter((collectionConfig) => collectionConfig.auth)
|
||||
.map((collectionConfig) => collectionConfig.slug),
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'editedAt',
|
||||
type: 'date',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'isLocked',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
name: 'user',
|
||||
type: 'relationship',
|
||||
relationTo: config.collections
|
||||
.filter((collectionConfig) => collectionConfig.auth)
|
||||
.map((collectionConfig) => collectionConfig.slug),
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -13,11 +13,6 @@ type CheckDocumentLockStatusArgs = {
|
||||
req: PayloadRequest
|
||||
}
|
||||
|
||||
type CheckDocumentLockResult = {
|
||||
lockedDocument?: JsonObject & TypeWithID
|
||||
shouldUnlockDocument: boolean
|
||||
}
|
||||
|
||||
export const checkDocumentLockStatus = async ({
|
||||
id,
|
||||
collectionSlug,
|
||||
@@ -25,7 +20,7 @@ export const checkDocumentLockStatus = async ({
|
||||
lockDurationDefault = 300, // Default 5 minutes in seconds
|
||||
lockErrorMessage,
|
||||
req,
|
||||
}: CheckDocumentLockStatusArgs): Promise<CheckDocumentLockResult> => {
|
||||
}: CheckDocumentLockStatusArgs): Promise<void> => {
|
||||
const { payload } = req
|
||||
|
||||
// Retrieve the lockDocuments property for either collection or global
|
||||
@@ -37,7 +32,7 @@ export const checkDocumentLockStatus = async ({
|
||||
|
||||
// If lockDocuments is explicitly set to false, skip the lock logic and return early
|
||||
if (isLockingEnabled === false) {
|
||||
return { lockedDocument: undefined, shouldUnlockDocument: false }
|
||||
return
|
||||
}
|
||||
|
||||
let lockedDocumentQuery = {}
|
||||
@@ -67,36 +62,36 @@ export const checkDocumentLockStatus = async ({
|
||||
limit: 1,
|
||||
pagination: false,
|
||||
req,
|
||||
sort: '-updatedAt',
|
||||
where: lockedDocumentQuery,
|
||||
})
|
||||
|
||||
let shouldUnlockDocument = false
|
||||
|
||||
// If there's a locked document, check lock conditions
|
||||
if (lockedDocumentResult.docs.length > 0) {
|
||||
const lockedDoc = lockedDocumentResult.docs[0]
|
||||
const lastEditedAt = new Date(lockedDoc?._lastEdited?.editedAt)
|
||||
const now = new Date()
|
||||
|
||||
const lockDuration =
|
||||
typeof lockDocumentsProp === 'object' ? lockDocumentsProp.duration : lockDurationDefault
|
||||
|
||||
const lockDurationInMilliseconds = lockDuration * 1000
|
||||
const currentUserId = req.user?.id
|
||||
|
||||
// If document is locked by another user and the lock hasn't expired
|
||||
if (lockedDoc._lastEdited?.user?.value?.id !== currentUserId) {
|
||||
if (now.getTime() - lastEditedAt.getTime() <= lockDurationInMilliseconds) {
|
||||
throw new APIError(finalLockErrorMessage)
|
||||
} else {
|
||||
// If lock has expired, allow unlocking
|
||||
shouldUnlockDocument = true
|
||||
}
|
||||
} else {
|
||||
// If document is locked by the current user, allow unlocking
|
||||
shouldUnlockDocument = true
|
||||
}
|
||||
const lockedDoc = lockedDocumentResult?.docs[0]
|
||||
if (!lockedDoc) {
|
||||
return
|
||||
}
|
||||
|
||||
return { lockedDocument: lockedDocumentResult.docs[0], shouldUnlockDocument }
|
||||
const lastEditedAt = new Date(lockedDoc?.editedAt)
|
||||
const now = new Date()
|
||||
|
||||
const lockDuration =
|
||||
typeof lockDocumentsProp === 'object' ? lockDocumentsProp.duration : lockDurationDefault
|
||||
|
||||
const lockDurationInMilliseconds = lockDuration * 1000
|
||||
const currentUserId = req.user?.id
|
||||
|
||||
// document is locked by another user and the lock hasn't expired
|
||||
if (
|
||||
lockedDoc.user?.value?.id !== currentUserId &&
|
||||
now.getTime() - lastEditedAt.getTime() <= lockDurationInMilliseconds
|
||||
) {
|
||||
throw new APIError(finalLockErrorMessage)
|
||||
}
|
||||
|
||||
await payload.db.deleteMany({
|
||||
collection: 'payload-locked-documents',
|
||||
req,
|
||||
where: lockedDocumentQuery,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@ const baseClass = 'select-row'
|
||||
export const SelectRow: React.FC = () => {
|
||||
const { selected, setSelection } = useSelection()
|
||||
const { rowData } = useTableCell()
|
||||
const { isLocked, userEditing } = rowData || {}
|
||||
const { _isLocked, _userEditing } = rowData || {}
|
||||
|
||||
const documentIsLocked = isLocked && userEditing
|
||||
const documentIsLocked = _isLocked && _userEditing
|
||||
|
||||
if (documentIsLocked) {
|
||||
return <Locked user={userEditing} />
|
||||
return <Locked user={_userEditing} />
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -193,10 +193,8 @@ const DocumentInfo: React.FC<
|
||||
// Send a patch request to update the _lastEdited info
|
||||
await requests.patch(`${serverURL}${api}/payload-locked-documents/${lockId}`, {
|
||||
body: JSON.stringify({
|
||||
_lastEdited: {
|
||||
editedAt: new Date(),
|
||||
user: { relationTo: user?.collection, value: user?.id },
|
||||
},
|
||||
editedAt: new Date(),
|
||||
user: { relationTo: user?.collection, value: user?.id },
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -230,7 +228,7 @@ const DocumentInfo: React.FC<
|
||||
const { docs } = await request.json()
|
||||
|
||||
if (docs.length > 0) {
|
||||
const newEditor = docs[0]._lastEdited?.user?.value
|
||||
const newEditor = docs[0].user?.value
|
||||
if (newEditor && newEditor.id !== currentEditor?.id) {
|
||||
setCurrentEditor(newEditor)
|
||||
setDocumentIsLocked(true)
|
||||
|
||||
@@ -56,8 +56,8 @@ export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalD
|
||||
const rows = new Map()
|
||||
if (allAvailable) {
|
||||
setSelectAll(SelectAllStatus.AllAvailable)
|
||||
docs.forEach(({ id, isLocked }) => {
|
||||
if (!isLocked) {
|
||||
docs.forEach(({ id, _isLocked }) => {
|
||||
if (!_isLocked) {
|
||||
rows.set(id, true)
|
||||
}
|
||||
})
|
||||
@@ -67,8 +67,8 @@ export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalD
|
||||
) {
|
||||
setSelectAll(SelectAllStatus.None)
|
||||
} else {
|
||||
docs.forEach(({ id, isLocked }) => {
|
||||
if (!isLocked) {
|
||||
docs.forEach(({ id, _isLocked }) => {
|
||||
if (!_isLocked) {
|
||||
rows.set(id, selectAll !== SelectAllStatus.Some)
|
||||
}
|
||||
})
|
||||
@@ -82,7 +82,7 @@ export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalD
|
||||
(id) => {
|
||||
const doc = docs.find((doc) => doc.id === id)
|
||||
|
||||
if (doc?.isLocked) {
|
||||
if (doc?._isLocked) {
|
||||
return // Prevent selection if the document is locked
|
||||
}
|
||||
|
||||
|
||||
@@ -258,43 +258,40 @@ export const buildFormState = async ({
|
||||
if (lockedDocument.docs && lockedDocument.docs.length > 0) {
|
||||
const lockedState = {
|
||||
isLocked: true,
|
||||
user: lockedDocument.docs[0]?._lastEdited?.user?.value,
|
||||
user: lockedDocument.docs[0]?.user?.value,
|
||||
}
|
||||
|
||||
if (updateLastEdited) {
|
||||
await req.payload.update({
|
||||
await req.payload.db.updateOne({
|
||||
id: lockedDocument.docs[0].id,
|
||||
collection: 'payload-locked-documents',
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
},
|
||||
editedAt: new Date().toISOString(),
|
||||
},
|
||||
req,
|
||||
})
|
||||
}
|
||||
|
||||
return { lockedState, state: result }
|
||||
} else {
|
||||
// If no lock document exists, create it
|
||||
await req.payload.create({
|
||||
await req.payload.db.create({
|
||||
collection: 'payload-locked-documents',
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: [req.user.collection],
|
||||
value: req.user.id,
|
||||
},
|
||||
},
|
||||
document: collectionSlug
|
||||
? {
|
||||
relationTo: [collectionSlug],
|
||||
value: id,
|
||||
}
|
||||
: undefined,
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: globalSlug ? globalSlug : undefined,
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: [req.user.collection],
|
||||
value: req.user.id,
|
||||
},
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
const lockedState = {
|
||||
|
||||
@@ -15,6 +15,7 @@ export interface Config {
|
||||
simple: Simple;
|
||||
media: Media;
|
||||
users: User;
|
||||
'payload-locked-documents': PayloadLockedDocument;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
@@ -162,6 +163,38 @@ export interface User {
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents".
|
||||
*/
|
||||
export interface PayloadLockedDocument {
|
||||
id: string;
|
||||
document?:
|
||||
| ({
|
||||
relationTo: 'posts';
|
||||
value: string | Post;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'simple';
|
||||
value: string | Simple;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'media';
|
||||
value: string | Media;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
} | null);
|
||||
globalSlug?: string | null;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
editedAt?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences".
|
||||
|
||||
@@ -89,19 +89,16 @@ describe('locked documents', () => {
|
||||
lockedDoc = await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
document: {
|
||||
relationTo: 'posts',
|
||||
value: postDoc.id,
|
||||
},
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: undefined,
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -292,19 +289,16 @@ describe('locked documents', () => {
|
||||
lockedDoc = await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
document: {
|
||||
relationTo: 'posts',
|
||||
value: postDoc.id,
|
||||
},
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: undefined,
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -399,19 +393,16 @@ describe('locked documents', () => {
|
||||
lockedDoc = await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
document: {
|
||||
relationTo: 'posts',
|
||||
value: postDoc.id,
|
||||
},
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: undefined,
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -462,10 +453,10 @@ describe('locked documents', () => {
|
||||
|
||||
const userEmail =
|
||||
// eslint-disable-next-line playwright/no-conditional-in-test
|
||||
lockedDoc.docs[0]._lastEdited.user.value &&
|
||||
typeof lockedDoc.docs[0]._lastEdited.user.value === 'object' &&
|
||||
'email' in lockedDoc.docs[0]._lastEdited.user.value &&
|
||||
lockedDoc.docs[0]._lastEdited.user.value.email
|
||||
lockedDoc.docs[0].user.value &&
|
||||
typeof lockedDoc.docs[0].user.value === 'object' &&
|
||||
'email' in lockedDoc.docs[0].user.value &&
|
||||
lockedDoc.docs[0].user.value.email
|
||||
|
||||
expect(userEmail).toEqual('dev@payloadcms.com')
|
||||
})
|
||||
@@ -492,19 +483,16 @@ describe('locked documents', () => {
|
||||
lockedDoc = await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
document: {
|
||||
relationTo: 'posts',
|
||||
value: postDoc.id,
|
||||
},
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: undefined,
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -557,10 +545,10 @@ describe('locked documents', () => {
|
||||
|
||||
const userEmail =
|
||||
// eslint-disable-next-line playwright/no-conditional-in-test
|
||||
lockedDoc.docs[0]._lastEdited.user.value &&
|
||||
typeof lockedDoc.docs[0]._lastEdited.user.value === 'object' &&
|
||||
'email' in lockedDoc.docs[0]._lastEdited.user.value &&
|
||||
lockedDoc.docs[0]._lastEdited.user.value.email
|
||||
lockedDoc.docs[0].user.value &&
|
||||
typeof lockedDoc.docs[0].user.value === 'object' &&
|
||||
'email' in lockedDoc.docs[0].user.value &&
|
||||
lockedDoc.docs[0].user.value.email
|
||||
|
||||
expect(userEmail).toEqual('dev@payloadcms.com')
|
||||
})
|
||||
@@ -618,11 +606,9 @@ describe('locked documents', () => {
|
||||
id: lockedDoc.docs[0].id,
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -671,11 +657,9 @@ describe('locked documents', () => {
|
||||
id: lockedDoc.docs[0].id,
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -729,11 +713,9 @@ describe('locked documents', () => {
|
||||
id: lockedDoc.docs[0].id,
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -784,16 +766,13 @@ describe('locked documents', () => {
|
||||
const lockedGlobal = await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
document: undefined,
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: 'menu',
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -138,19 +138,16 @@ describe('Locked documents', () => {
|
||||
const lockedDocInstance = await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: pastEditedAt.toISOString(), // stale date
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
editedAt: pastEditedAt.toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
document: {
|
||||
relationTo: 'posts',
|
||||
value: newPost2.id,
|
||||
},
|
||||
globalSlug: undefined,
|
||||
isLocked: true,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -198,16 +195,13 @@ describe('Locked documents', () => {
|
||||
const lockedGlobalInstance = await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: pastEditedAt.toISOString(), // stale date
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
editedAt: pastEditedAt.toISOString(), // stale date
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
document: undefined,
|
||||
globalSlug: menuSlug,
|
||||
isLocked: true,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -256,19 +250,16 @@ describe('Locked documents', () => {
|
||||
await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
document: {
|
||||
relationTo: 'posts',
|
||||
value: newPost.id,
|
||||
},
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: undefined,
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -294,16 +285,13 @@ describe('Locked documents', () => {
|
||||
await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
document: undefined,
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: menuSlug,
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -336,19 +324,16 @@ describe('Locked documents', () => {
|
||||
await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: new Date().toISOString(),
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
document: {
|
||||
relationTo: 'posts',
|
||||
value: newPost3.id,
|
||||
},
|
||||
editedAt: new Date().toISOString(),
|
||||
globalSlug: undefined,
|
||||
isLocked: true,
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -380,19 +365,16 @@ describe('Locked documents', () => {
|
||||
const lockedDocInstance = await payload.create({
|
||||
collection: lockedDocumentCollection,
|
||||
data: {
|
||||
_lastEdited: {
|
||||
editedAt: pastEditedAt.toISOString(), // stale date
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
editedAt: pastEditedAt.toISOString(), // stale date
|
||||
user: {
|
||||
relationTo: 'users',
|
||||
value: user2.id,
|
||||
},
|
||||
document: {
|
||||
relationTo: 'posts',
|
||||
value: newPost4.id,
|
||||
},
|
||||
globalSlug: undefined,
|
||||
isLocked: true,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -13,10 +13,9 @@ export interface Config {
|
||||
collections: {
|
||||
pages: Page;
|
||||
posts: Post;
|
||||
simple: Simple;
|
||||
users: User;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-locked-documents': PayloadLockedDocument;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
db: {
|
||||
@@ -24,7 +23,6 @@ export interface Config {
|
||||
};
|
||||
globals: {
|
||||
menu: Menu;
|
||||
'custom-ts': CustomT;
|
||||
};
|
||||
locale: null;
|
||||
user: User & {
|
||||
@@ -56,37 +54,6 @@ export interface UserAuthOperations {
|
||||
export interface Page {
|
||||
id: string;
|
||||
text?: string | null;
|
||||
richText?: {
|
||||
root: {
|
||||
type: string;
|
||||
children: {
|
||||
type: string;
|
||||
version: number;
|
||||
[k: string]: unknown;
|
||||
}[];
|
||||
direction: ('ltr' | 'rtl') | null;
|
||||
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||
indent: number;
|
||||
version: number;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
} | null;
|
||||
myBlocks?:
|
||||
| (
|
||||
| {
|
||||
test?: string | null;
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'test';
|
||||
}
|
||||
| {
|
||||
test2?: string | null;
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'someBlock2';
|
||||
}
|
||||
)[]
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
_status?: ('draft' | 'published') | null;
|
||||
@@ -98,51 +65,10 @@ export interface Page {
|
||||
export interface Post {
|
||||
id: string;
|
||||
text?: string | null;
|
||||
richText?: {
|
||||
root: {
|
||||
type: string;
|
||||
children: {
|
||||
type: string;
|
||||
version: number;
|
||||
[k: string]: unknown;
|
||||
}[];
|
||||
direction: ('ltr' | 'rtl') | null;
|
||||
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||
indent: number;
|
||||
version: number;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
} | null;
|
||||
myBlocks?:
|
||||
| (
|
||||
| {
|
||||
test?: string | null;
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'test';
|
||||
}
|
||||
| {
|
||||
test2?: string | null;
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'someBlock2';
|
||||
}
|
||||
)[]
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
_status?: ('draft' | 'published') | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "simple".
|
||||
*/
|
||||
export interface Simple {
|
||||
id: string;
|
||||
text?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
@@ -161,6 +87,34 @@ export interface User {
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents".
|
||||
*/
|
||||
export interface PayloadLockedDocument {
|
||||
id: string;
|
||||
document?:
|
||||
| ({
|
||||
relationTo: 'pages';
|
||||
value: string | Page;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'posts';
|
||||
value: string | Post;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
} | null);
|
||||
globalSlug?: string | null;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
editedAt?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences".
|
||||
@@ -184,45 +138,6 @@ export interface PayloadPreference {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents".
|
||||
*/
|
||||
export interface PayloadLockedDocument {
|
||||
id: string;
|
||||
document?:
|
||||
| ({
|
||||
relationTo: 'pages';
|
||||
value: string | Page;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'posts';
|
||||
value: string | Post;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'simple';
|
||||
value: string | Simple;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'payload-preferences';
|
||||
value: string | PayloadPreference;
|
||||
} | null);
|
||||
globalSlug?: string | null;
|
||||
_lastEdited: {
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
editedAt?: string | null;
|
||||
};
|
||||
isLocked?: boolean | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-migrations".
|
||||
@@ -244,29 +159,6 @@ export interface Menu {
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-ts".
|
||||
*/
|
||||
export interface CustomT {
|
||||
id: string;
|
||||
custom?: 'hello' | 'world';
|
||||
withDefinitionsUsage?: ObjectWithNumber[];
|
||||
json: {
|
||||
id: string;
|
||||
name: string;
|
||||
age?: number;
|
||||
}[];
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "objectWithNumber".
|
||||
*/
|
||||
export interface ObjectWithNumber {
|
||||
id?: number;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "auth".
|
||||
|
||||
Reference in New Issue
Block a user