fix: do not display field if read permission is false - admin panel ui (#3949)

This commit is contained in:
Jarrod Flesch
2023-11-01 10:21:19 -04:00
committed by GitHub
parent a5b2333140
commit cdc10be1a2
4 changed files with 140 additions and 51 deletions

View File

@@ -48,23 +48,24 @@ export const filterFields = (args: {
} }
const isFieldAffectingData = fieldAffectsData(field) const isFieldAffectingData = fieldAffectsData(field)
const fieldPermissions = isFieldAffectingData ? permissions?.[field.name] : permissions const fieldPermissions = isFieldAffectingData ? permissions?.[field.name] : permissions
// if the user cannot read the field, then filter it out
if (fieldPermissions?.read?.permission === false) {
return acc
}
// readOnly from field config
let readOnly = field.admin && 'readOnly' in field.admin ? field.admin.readOnly : undefined let readOnly = field.admin && 'readOnly' in field.admin ? field.admin.readOnly : undefined
// if parent field is readOnly
// but this field is `readOnly: false`
// the field should be editable
if (readOnlyOverride && readOnly !== false) readOnly = true if (readOnlyOverride && readOnly !== false) readOnly = true
if ( // unless the user does not pass access control
(isFieldAffectingData && permissions?.[field?.name]?.read?.permission !== false) || if (fieldPermissions?.[operation]?.permission === false) {
!isFieldAffectingData readOnly = true
) {
if (
isFieldAffectingData &&
permissions?.[field?.name]?.[operation]?.permission === false
) {
readOnly = true
}
} }
if (FieldComponent) { if (FieldComponent) {

View File

@@ -52,7 +52,22 @@ export default buildConfigWithDefaults({
setTimeout(resolve, 50, true) // set to 'true' or 'false' here to simulate the response setTimeout(resolve, 50, true) // set to 'true' or 'false' here to simulate the response
}), }),
}, },
fields: [], fields: [
{
name: 'roles',
type: 'select',
hasMany: true,
options: ['admin', 'user'],
defaultValue: ['user'],
access: {
create: ({ req }) => req.user?.roles?.includes('admin'),
read: () => false,
update: ({ req }) => {
return req.user?.roles?.includes('admin')
},
},
},
],
}, },
{ {
slug, slug,

View File

@@ -125,6 +125,14 @@ describe('access control', () => {
}) })
}) })
describe('restricted fields', () => {
test('should not show field without permission', async () => {
await page.goto(url.account)
await wait(500)
await expect(page.locator('#field-roles')).toBeHidden()
})
})
describe('read-only collection', () => { describe('read-only collection', () => {
let existingDoc: ReadOnlyCollection let existingDoc: ReadOnlyCollection

View File

@@ -1,4 +1,5 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* This file was automatically generated by Payload. * This file was automatically generated by Payload.
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
@@ -9,92 +10,156 @@ export interface Config {
collections: { collections: {
users: User users: User
posts: Post posts: Post
unrestricted: Unrestricted
restricted: Restricted restricted: Restricted
'read-only-collection': ReadOnlyCollection 'read-only-collection': ReadOnlyCollection
'user-restricted': UserRestricted
'restricted-versions': RestrictedVersion 'restricted-versions': RestrictedVersion
'sibling-data': SiblingDatum 'sibling-data': SiblingDatum
'rely-on-request-headers': RelyOnRequestHeader 'rely-on-request-headers': RelyOnRequestHeader
'doc-level-access': DocLevelAccess 'doc-level-access': DocLevelAccess
'hidden-fields': HiddenField 'hidden-fields': HiddenField
'hidden-access': HiddenAccess
'payload-preferences': PayloadPreference
'payload-migrations': PayloadMigration
} }
globals: {} globals: {}
} }
export interface User { export interface User {
id: string id: string
email?: string roles?: ('admin' | 'user')[] | null
resetPasswordToken?: string
resetPasswordExpiration?: string
loginAttempts?: number
lockUntil?: string
createdAt: string
updatedAt: string updatedAt: string
password?: string createdAt: string
email: string
resetPasswordToken?: string | null
resetPasswordExpiration?: string | null
salt?: string | null
hash?: string | null
loginAttempts?: number | null
lockUntil?: string | null
password: string | null
} }
export interface Post { export interface Post {
id: string id: string
restrictedField?: string restrictedField?: string | null
group?: { group?: {
restrictedGroupText?: string restrictedGroupText?: string | null
} }
restrictedRowText?: string restrictedRowText?: string | null
restrictedCollapsibleText?: string restrictedCollapsibleText?: string | null
createdAt: string
updatedAt: string updatedAt: string
createdAt: string
}
export interface Unrestricted {
id: string
name?: string | null
userRestrictedDocs?: (string | UserRestricted)[] | null
updatedAt: string
createdAt: string
}
export interface UserRestricted {
id: string
name?: string | null
updatedAt: string
createdAt: string
} }
export interface Restricted { export interface Restricted {
id: string id: string
name?: string name?: string | null
createdAt: string
updatedAt: string updatedAt: string
createdAt: string
} }
export interface ReadOnlyCollection { export interface ReadOnlyCollection {
id: string id: string
name?: string name?: string | null
createdAt: string
updatedAt: string updatedAt: string
createdAt: string
} }
export interface RestrictedVersion { export interface RestrictedVersion {
id: string id: string
name?: string name?: string | null
createdAt: string hidden?: boolean | null
updatedAt: string updatedAt: string
createdAt: string
} }
export interface SiblingDatum { export interface SiblingDatum {
id: string id: string
array?: { array?:
allowPublicReadability?: boolean | {
text?: string allowPublicReadability?: boolean | null
id?: string text?: string | null
}[] id?: string | null
createdAt: string }[]
| null
updatedAt: string updatedAt: string
createdAt: string
} }
export interface RelyOnRequestHeader { export interface RelyOnRequestHeader {
id: string id: string
name?: string name?: string | null
createdAt: string
updatedAt: string updatedAt: string
createdAt: string
} }
export interface DocLevelAccess { export interface DocLevelAccess {
id: string id: string
approvedForRemoval?: boolean approvedForRemoval?: boolean | null
approvedTitle?: string approvedTitle?: string | null
lockTitle?: boolean lockTitle?: boolean | null
createdAt: string
updatedAt: string updatedAt: string
createdAt: string
} }
export interface HiddenField { export interface HiddenField {
id: string id: string
title?: string title?: string | null
partiallyHiddenGroup?: { partiallyHiddenGroup?: {
name?: string name?: string | null
value?: string value?: string | null
} }
partiallyHiddenArray?: { partiallyHiddenArray?:
name?: string | {
value?: string name?: string | null
id?: string value?: string | null
}[] id?: string | null
createdAt: string }[]
| null
hidden?: boolean | null
updatedAt: string updatedAt: string
createdAt: string
}
export interface HiddenAccess {
id: string
title: string
hidden?: boolean | null
updatedAt: string
createdAt: string
}
export interface PayloadPreference {
id: string
user: {
relationTo: 'users'
value: string | User
}
key?: string | null
value?:
| {
[k: string]: unknown
}
| unknown[]
| string
| number
| boolean
| null
updatedAt: string
createdAt: string
}
export interface PayloadMigration {
id: string
name?: string | null
batch?: number | null
updatedAt: string
createdAt: string
}
declare module 'payload' {
export interface GeneratedTypes extends Config {}
} }