Skip to content

Commit 2b941b7

Browse files
authored
fix(next,ui): fixes global doc permissions and optimizes publish access data loading (#6451)
1 parent db772a0 commit 2b941b7

File tree

19 files changed

+537
-264
lines changed

19 files changed

+537
-264
lines changed

packages/next/src/routes/rest/auth/access.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,29 @@ import type { BaseRouteHandler } from '../types.js'
66
import { headersWithCors } from '../../../utilities/headersWithCors.js'
77

88
export const access: BaseRouteHandler = async ({ req }) => {
9-
const results = await accessOperation({
9+
const headers = headersWithCors({
10+
headers: new Headers(),
1011
req,
1112
})
1213

13-
return Response.json(results, {
14-
headers: headersWithCors({
15-
headers: new Headers(),
14+
try {
15+
const results = await accessOperation({
1616
req,
17-
}),
18-
status: httpStatus.OK,
19-
})
17+
})
18+
19+
return Response.json(results, {
20+
headers,
21+
status: httpStatus.OK,
22+
})
23+
} catch (e: unknown) {
24+
return Response.json(
25+
{
26+
error: e,
27+
},
28+
{
29+
headers,
30+
status: httpStatus.INTERNAL_SERVER_ERROR,
31+
},
32+
)
33+
}
2034
}

packages/next/src/views/Account/index.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,21 @@ import { FormQueryParamsProvider } from '@payloadcms/ui/providers/FormQueryParam
99
import { notFound } from 'next/navigation.js'
1010
import React from 'react'
1111

12+
import { getDocumentPermissions } from '../Document/getDocumentPermissions.js'
1213
import { EditView } from '../Edit/index.js'
1314
import { Settings } from './Settings/index.js'
1415

1516
export { generateAccountMetadata } from './meta.js'
1617

17-
export const Account: React.FC<AdminViewProps> = ({ initPageResult, params, searchParams }) => {
18+
export const Account: React.FC<AdminViewProps> = async ({
19+
initPageResult,
20+
params,
21+
searchParams,
22+
}) => {
1823
const {
1924
locale,
2025
permissions,
26+
req,
2127
req: {
2228
i18n,
2329
payload,
@@ -32,11 +38,17 @@ export const Account: React.FC<AdminViewProps> = ({ initPageResult, params, sear
3238
serverURL,
3339
} = config
3440

35-
const collectionPermissions = permissions?.collections?.[userSlug]
36-
3741
const collectionConfig = config.collections.find((collection) => collection.slug === userSlug)
3842

3943
if (collectionConfig) {
44+
const { docPermissions, hasPublishPermission, hasSavePermission } =
45+
await getDocumentPermissions({
46+
id: user.id,
47+
collectionConfig,
48+
data: user,
49+
req,
50+
})
51+
4052
const viewComponentProps: ServerSideEditViewProps = {
4153
initPageResult,
4254
params,
@@ -50,9 +62,10 @@ export const Account: React.FC<AdminViewProps> = ({ initPageResult, params, sear
5062
action={`${serverURL}${api}/${userSlug}${user?.id ? `/${user.id}` : ''}`}
5163
apiURL={`${serverURL}${api}/${userSlug}${user?.id ? `/${user.id}` : ''}`}
5264
collectionSlug={userSlug}
53-
docPermissions={collectionPermissions}
54-
hasSavePermission={collectionPermissions?.update?.permission}
55-
id={user?.id}
65+
docPermissions={docPermissions}
66+
hasPublishPermission={hasPublishPermission}
67+
hasSavePermission={hasSavePermission}
68+
id={user?.id.toString()}
5669
isEditing
5770
>
5871
<DocumentHeader
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type {
2+
Data,
3+
Payload,
4+
PayloadRequest,
5+
SanitizedCollectionConfig,
6+
SanitizedGlobalConfig,
7+
} from 'payload/types'
8+
9+
export const getDocumentData = async (args: {
10+
collectionConfig?: SanitizedCollectionConfig
11+
globalConfig?: SanitizedGlobalConfig
12+
id?: number | string
13+
locale: Locale
14+
payload: Payload
15+
req: PayloadRequest
16+
}): Promise<Data> => {
17+
const { id, collectionConfig, globalConfig, locale, payload, req } = args
18+
19+
let data: Data
20+
21+
if (collectionConfig && id !== undefined && id !== null) {
22+
data = await payload.findByID({
23+
id,
24+
collection: collectionConfig.slug,
25+
depth: 0,
26+
locale: locale.code,
27+
req,
28+
})
29+
}
30+
31+
if (globalConfig) {
32+
data = await payload.findGlobal({
33+
slug: globalConfig.slug,
34+
depth: 0,
35+
locale: locale.code,
36+
req,
37+
})
38+
}
39+
40+
return data
41+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import type { DocumentPermissions } from 'payload/auth'
2+
import type {
3+
Data,
4+
PayloadRequest,
5+
SanitizedCollectionConfig,
6+
SanitizedGlobalConfig,
7+
} from 'payload/types'
8+
9+
import { hasSavePermission as getHasSavePermission } from '@payloadcms/ui/utilities/hasSavePermission'
10+
import { isEditing as getIsEditing } from '@payloadcms/ui/utilities/isEditing'
11+
import { docAccessOperation, docAccessOperationGlobal } from 'payload/operations'
12+
13+
export const getDocumentPermissions = async (args: {
14+
collectionConfig?: SanitizedCollectionConfig
15+
data: Data
16+
globalConfig?: SanitizedGlobalConfig
17+
id?: number | string
18+
req: PayloadRequest
19+
}): Promise<{
20+
docPermissions: DocumentPermissions
21+
hasPublishPermission: boolean
22+
hasSavePermission: boolean
23+
}> => {
24+
const { id, collectionConfig, data = {}, globalConfig, req } = args
25+
26+
let docPermissions: DocumentPermissions
27+
let hasPublishPermission = false
28+
29+
if (collectionConfig) {
30+
try {
31+
docPermissions = await docAccessOperation({
32+
id: id?.toString(),
33+
collection: {
34+
config: collectionConfig,
35+
},
36+
req: {
37+
...req,
38+
data,
39+
},
40+
})
41+
42+
if (collectionConfig.versions?.drafts) {
43+
hasPublishPermission = await docAccessOperation({
44+
id: id?.toString(),
45+
collection: {
46+
config: collectionConfig,
47+
},
48+
req: {
49+
...req,
50+
data: {
51+
...data,
52+
_status: 'published',
53+
},
54+
},
55+
}).then(({ update }) => update?.permission)
56+
}
57+
} catch (error) {
58+
console.error(error) // eslint-disable-line no-console
59+
}
60+
}
61+
62+
if (globalConfig) {
63+
try {
64+
docPermissions = await docAccessOperationGlobal({
65+
globalConfig,
66+
req: {
67+
...req,
68+
data,
69+
},
70+
})
71+
72+
if (globalConfig.versions?.drafts) {
73+
hasPublishPermission = await docAccessOperationGlobal({
74+
globalConfig,
75+
req: {
76+
...req,
77+
data: {
78+
...data,
79+
_status: 'published',
80+
},
81+
},
82+
}).then(({ update }) => update?.permission)
83+
}
84+
} catch (error) {
85+
console.error(error) // eslint-disable-line no-console
86+
}
87+
}
88+
89+
const hasSavePermission = getHasSavePermission({
90+
collectionSlug: collectionConfig?.slug,
91+
docPermissions,
92+
globalSlug: globalConfig?.slug,
93+
isEditing: getIsEditing({
94+
id,
95+
collectionSlug: collectionConfig?.slug,
96+
globalSlug: globalConfig?.slug,
97+
}),
98+
})
99+
100+
return {
101+
docPermissions,
102+
hasPublishPermission,
103+
hasSavePermission,
104+
}
105+
}

packages/next/src/views/Document/index.tsx

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { EditViewComponent } from 'payload/config'
22
import type { AdminViewComponent, ServerSideEditViewProps } from 'payload/types'
3-
import type { DocumentPermissions } from 'payload/types'
43
import type { AdminViewProps } from 'payload/types'
54

65
import { DocumentHeader } from '@payloadcms/ui/elements/DocumentHeader'
@@ -9,15 +8,15 @@ import { RenderCustomComponent } from '@payloadcms/ui/elements/RenderCustomCompo
98
import { DocumentInfoProvider } from '@payloadcms/ui/providers/DocumentInfo'
109
import { EditDepthProvider } from '@payloadcms/ui/providers/EditDepth'
1110
import { FormQueryParamsProvider } from '@payloadcms/ui/providers/FormQueryParams'
12-
import { hasSavePermission as getHasSavePermission } from '@payloadcms/ui/utilities/hasSavePermission'
1311
import { isEditing as getIsEditing } from '@payloadcms/ui/utilities/isEditing'
1412
import { notFound, redirect } from 'next/navigation.js'
15-
import { docAccessOperation } from 'payload/operations'
1613
import React from 'react'
1714

1815
import type { GenerateEditViewMetadata } from './getMetaBySegment.js'
1916

2017
import { NotFoundView } from '../NotFound/index.js'
18+
import { getDocumentData } from './getDocumentData.js'
19+
import { getDocumentPermissions } from './getDocumentPermissions.js'
2120
import { getMetaBySegment } from './getMetaBySegment.js'
2221
import { getViewsFromConfig } from './getViewsFromConfig.js'
2322

@@ -61,32 +60,33 @@ export const Document: React.FC<AdminViewProps> = async ({
6160
let DefaultView: EditViewComponent
6261
let ErrorView: AdminViewComponent
6362

64-
let docPermissions: DocumentPermissions
65-
let hasSavePermission: boolean
6663
let apiURL: string
6764
let action: string
6865

66+
const data = await getDocumentData({
67+
id,
68+
collectionConfig,
69+
globalConfig,
70+
locale,
71+
payload,
72+
req,
73+
})
74+
75+
const { docPermissions, hasPublishPermission, hasSavePermission } = await getDocumentPermissions({
76+
id,
77+
collectionConfig,
78+
data,
79+
globalConfig,
80+
req,
81+
})
82+
6983
if (collectionConfig) {
7084
if (!visibleEntities?.collections?.find((visibleSlug) => visibleSlug === collectionSlug)) {
7185
notFound()
7286
}
7387

74-
try {
75-
docPermissions = await docAccessOperation({
76-
id,
77-
collection: {
78-
config: collectionConfig,
79-
},
80-
req,
81-
})
82-
} catch (error) {
83-
notFound()
84-
}
85-
8688
action = `${serverURL}${apiRoute}/${collectionSlug}${isEditing ? `/${id}` : ''}`
8789

88-
hasSavePermission = getHasSavePermission({ collectionSlug, docPermissions, isEditing })
89-
9090
apiURL = `${serverURL}${apiRoute}/${collectionSlug}/${id}?locale=${locale.code}${
9191
collectionConfig.versions?.drafts ? '&draft=true' : ''
9292
}`
@@ -117,9 +117,6 @@ export const Document: React.FC<AdminViewProps> = async ({
117117
notFound()
118118
}
119119

120-
docPermissions = permissions?.globals?.[globalSlug]
121-
hasSavePermission = getHasSavePermission({ docPermissions, globalSlug, isEditing })
122-
123120
action = `${serverURL}${apiRoute}/globals/${globalSlug}`
124121

125122
apiURL = `${serverURL}${apiRoute}/${globalSlug}?locale=${locale.code}${
@@ -191,6 +188,7 @@ export const Document: React.FC<AdminViewProps> = async ({
191188
disableActions={false}
192189
docPermissions={docPermissions}
193190
globalSlug={globalConfig?.slug}
191+
hasPublishPermission={hasPublishPermission}
194192
hasSavePermission={hasSavePermission}
195193
id={id}
196194
isEditing={isEditing}

packages/next/src/views/Edit/Default/index.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ export const DefaultEditView: React.FC = () => {
4444
disableActions,
4545
disableLeaveWithoutSaving,
4646
docPermissions,
47-
getDocPermissions,
4847
getDocPreferences,
4948
getVersions,
5049
globalSlug,
50+
hasPublishPermission,
5151
hasSavePermission,
5252
initialData: data,
5353
initialState,
@@ -115,7 +115,6 @@ export const DefaultEditView: React.FC = () => {
115115
}
116116

117117
void getVersions()
118-
void getDocPermissions()
119118

120119
if (typeof onSaveFromContext === 'function') {
121120
void onSaveFromContext({
@@ -147,7 +146,6 @@ export const DefaultEditView: React.FC = () => {
147146
depth,
148147
collectionSlug,
149148
getVersions,
150-
getDocPermissions,
151149
isEditing,
152150
refreshCookieAsync,
153151
adminRoute,
@@ -221,6 +219,7 @@ export const DefaultEditView: React.FC = () => {
221219
apiURL={apiURL}
222220
data={data}
223221
disableActions={disableActions}
222+
hasPublishPermission={hasPublishPermission}
224223
hasSavePermission={hasSavePermission}
225224
id={id}
226225
isEditing={isEditing}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const PreviewView: React.FC<Props> = ({
6161
docPermissions,
6262
getDocPreferences,
6363
globalSlug,
64+
hasPublishPermission,
6465
hasSavePermission,
6566
initialData,
6667
initialState,
@@ -160,6 +161,7 @@ const PreviewView: React.FC<Props> = ({
160161
apiURL={apiURL}
161162
data={initialData}
162163
disableActions={disableActions}
164+
hasPublishPermission={hasPublishPermission}
163165
hasSavePermission={hasSavePermission}
164166
id={id}
165167
isEditing={isEditing}

packages/ui/src/elements/DocumentControls/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const DocumentControls: React.FC<{
2727
apiURL: string
2828
data?: any
2929
disableActions?: boolean
30+
hasPublishPermission?: boolean
3031
hasSavePermission?: boolean
3132
id?: number | string
3233
isAccountView?: boolean

0 commit comments

Comments
 (0)