fix: do not display field if read permission is false - admin panel ui (#3949)
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user