fix(db-postgres): allow for nested block fields to be queried (#4237)

Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
This commit is contained in:
Jarrod Flesch
2023-11-29 11:03:57 -05:00
committed by GitHub
parent 6d28fc46bd
commit cd07873fc5
4 changed files with 96 additions and 9 deletions

View File

@@ -297,6 +297,9 @@ export const getTableColumnFromPath = ({
table: adapter.tables[newTableName], table: adapter.tables[newTableName],
} }
} }
if (pathSegments[1] === 'blockType') {
throw new APIError('Querying on blockType is not supported')
}
break break
} }

View File

@@ -33,7 +33,11 @@ type Args = {
const flattenWhere = (query: Where): WhereField[] => const flattenWhere = (query: Where): WhereField[] =>
Object.entries(query).reduce((flattenedConstraints, [key, val]) => { Object.entries(query).reduce((flattenedConstraints, [key, val]) => {
if ((key === 'and' || key === 'or') && Array.isArray(val)) { if ((key === 'and' || key === 'or') && Array.isArray(val)) {
return [...flattenedConstraints, ...val.map((subVal) => flattenWhere(subVal))] const subWhereConstraints: Where[] = val.reduce((acc, subVal) => {
const subWhere = flattenWhere(subVal)
return [...acc, ...subWhere]
}, [])
return [...flattenedConstraints, ...subWhereConstraints]
} }
return [...flattenedConstraints, { [key]: val }] return [...flattenedConstraints, { [key]: val }]

View File

@@ -116,12 +116,24 @@ export async function validateSearchParam({
const segments = fieldPath.split('.') const segments = fieldPath.split('.')
if (versionFields) { if (versionFields) {
if (fieldPath === 'parent' || fieldPath === 'version') { fieldAccess = policies[entityType][entitySlug]
fieldAccess = policies[entityType][entitySlug].read.permission if (segments[0] === 'parent' || segments[0] === 'version') {
} else if (segments[0] === 'parent' || segments[0] === 'version') {
fieldAccess = policies[entityType][entitySlug].read.permission
segments.shift() segments.shift()
} else {
segments.forEach((segment, pathIndex) => {
if (fieldAccess[segment]) {
if (pathIndex === segments.length - 1) {
fieldAccess = fieldAccess[segment]
} else if ('fields' in fieldAccess[segment]) {
fieldAccess = fieldAccess[segment].fields
} else if ('blocks' in fieldAccess[segment]) {
fieldAccess = fieldAccess[segment]
}
}
})
} }
fieldAccess = fieldAccess.read.permission
} else { } else {
fieldAccess = policies[entityType][entitySlug].fields fieldAccess = policies[entityType][entitySlug].fields
@@ -129,10 +141,14 @@ export async function validateSearchParam({
fieldAccess = fieldAccess[field.name] fieldAccess = fieldAccess[field.name]
} else { } else {
segments.forEach((segment, pathIndex) => { segments.forEach((segment, pathIndex) => {
if (pathIndex === segments.length - 1) { if (fieldAccess[segment]) {
fieldAccess = fieldAccess[segment] if (pathIndex === segments.length - 1) {
} else { fieldAccess = fieldAccess[segment]
fieldAccess = fieldAccess[segment].fields } else if ('fields' in fieldAccess[segment]) {
fieldAccess = fieldAccess[segment].fields
} else if ('blocks' in fieldAccess[segment]) {
fieldAccess = fieldAccess[segment]
}
} }
}) })
} }

View File

@@ -8,6 +8,7 @@ import type { PaginatedDocs } from '../../packages/payload/src/database/types'
import type { RichTextField } from './payload-types' import type { RichTextField } from './payload-types'
import payload from '../../packages/payload/src' import payload from '../../packages/payload/src'
import { devUser } from '../credentials'
import { initPayloadTest } from '../helpers/configHelpers' import { initPayloadTest } from '../helpers/configHelpers'
import { isMongoose } from '../helpers/isMongoose' import { isMongoose } from '../helpers/isMongoose'
import { RESTClient } from '../helpers/rest' import { RESTClient } from '../helpers/rest'
@@ -35,6 +36,7 @@ let graphQLClient: GraphQLClient
let serverURL: string let serverURL: string
let config: SanitizedConfig let config: SanitizedConfig
let token: string let token: string
let user: any
describe('Fields', () => { describe('Fields', () => {
beforeAll(async () => { beforeAll(async () => {
@@ -45,6 +47,14 @@ describe('Fields', () => {
const graphQLURL = `${serverURL}${config.routes.api}${config.routes.graphQL}` const graphQLURL = `${serverURL}${config.routes.api}${config.routes.graphQL}`
graphQLClient = new GraphQLClient(graphQLURL) graphQLClient = new GraphQLClient(graphQLURL)
token = await client.login() token = await client.login()
user = await payload.login({
collection: 'users',
data: {
email: devUser.email,
password: devUser.password,
},
})
}) })
beforeEach(async () => { beforeEach(async () => {
@@ -834,6 +844,60 @@ describe('Fields', () => {
expect(result.id).toBeDefined() expect(result.id).toBeDefined()
}) })
it('should filter based on nested block fields', async () => {
await payload.create({
collection: 'block-fields',
data: {
blocks: [
{
blockType: 'content',
text: 'green',
},
],
},
})
await payload.create({
collection: 'block-fields',
data: {
blocks: [
{
blockType: 'content',
text: 'pink',
},
],
},
})
await payload.create({
collection: 'block-fields',
data: {
blocks: [
{
blockType: 'content',
text: 'green',
},
],
},
})
const blockFields = await payload.find({
collection: 'block-fields',
overrideAccess: false,
user,
where: {
and: [
{
'blocks.text': {
equals: 'green',
},
},
],
},
})
const { docs } = blockFields
expect(docs).toHaveLength(2)
})
}) })
describe('json', () => { describe('json', () => {