Files
klz-cables.com/.pnpm-store/v10/files/f3/71f9caaa9091ed725e815f73f5b7d1a436de5b61492f2894594766c1caf58f4f607ad4f2f3c08307082071c1c2f11b98d5d6b5d4c7542fa14e20e25ba58097
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

164 lines
6.6 KiB
Plaintext

import { fieldAffectsData } from '../../fields/config/types.js';
import { getEntityPermissions } from '../../utilities/getEntityPermissions/getEntityPermissions.js';
import { isolateObjectProperty } from '../../utilities/isolateObjectProperty.js';
import { getLocalizedPaths } from '../getLocalizedPaths.js';
import { validateQueryPaths } from './validateQueryPaths.js';
/**
* Validate the Payload key / value / operator
*/ export async function validateSearchParam({ collectionConfig, constraint, errors, fields, globalConfig, operator, overrideAccess, parentIsLocalized, path: incomingPath, policies, polymorphicJoin, req, val, versionFields }) {
// Replace GraphQL nested field double underscore formatting
let sanitizedPath;
if (incomingPath === '_id') {
sanitizedPath = 'id';
} else {
sanitizedPath = incomingPath.replace(/__/g, '.');
}
let paths = [];
const { slug } = collectionConfig || globalConfig;
const blockReferencesPermissions = {};
if (globalConfig && !policies.globals[slug]) {
policies.globals[slug] = await getEntityPermissions({
blockReferencesPermissions,
entity: globalConfig,
entityType: 'global',
fetchData: false,
operations: [
'read'
],
req
});
}
if (sanitizedPath !== 'id') {
paths = getLocalizedPaths({
collectionSlug: collectionConfig?.slug,
fields,
globalSlug: globalConfig?.slug,
incomingPath: sanitizedPath,
locale: req.locale,
overrideAccess,
parentIsLocalized,
payload: req.payload
});
}
const promises = [];
// Sanitize relation.otherRelation.id to relation.otherRelation
if (paths.at(-1)?.path === 'id') {
const previousField = paths.at(-2)?.field;
if (previousField && (previousField.type === 'relationship' || previousField.type === 'upload') && typeof previousField.relationTo === 'string') {
paths.pop();
}
}
promises.push(...paths.map(async ({ collectionSlug, field, invalid, path }, i)=>{
if (invalid) {
if (!polymorphicJoin) {
errors.push({
path
});
}
return;
}
// where: { relatedPosts: { equals: 1}} -> { 'relatedPosts.id': { equals: 1}}
if (field.type === 'join' && path === incomingPath) {
constraint[`${path}.id`] = constraint[path];
delete constraint[path];
}
if ('virtual' in field && field.virtual) {
if (field.virtual === true) {
errors.push({
path
});
}
}
if (polymorphicJoin && path === 'relationTo') {
return;
}
if (!overrideAccess && fieldAffectsData(field)) {
if (collectionSlug) {
if (!policies.collections[collectionSlug]) {
policies.collections[collectionSlug] = await getEntityPermissions({
blockReferencesPermissions,
entity: req.payload.collections[collectionSlug].config,
entityType: 'collection',
fetchData: false,
operations: [
'read'
],
req: isolateObjectProperty(req, 'transactionID')
});
}
if ([
'hash',
'salt'
].includes(incomingPath) && collectionConfig.auth && !collectionConfig.auth?.disableLocalStrategy) {
errors.push({
path: incomingPath
});
}
}
let fieldPath = path;
// remove locale from end of path
if (path.endsWith(`.${req.locale}`)) {
fieldPath = path.slice(0, -(req.locale.length + 1));
}
// remove ".value" from ends of polymorphic relationship paths
if ((field.type === 'relationship' || field.type === 'upload') && Array.isArray(field.relationTo)) {
fieldPath = fieldPath.replace('.value', '');
}
const entityType = globalConfig ? 'globals' : 'collections';
const entitySlug = collectionSlug || globalConfig.slug;
const segments = fieldPath.split('.');
let fieldAccess;
if (versionFields) {
fieldAccess = policies[entityType][entitySlug].fields;
if (segments[0] === 'parent' || segments[0] === 'version' || segments[0] === 'snapshot' || segments[0] === 'latest') {
segments.shift();
}
} else {
fieldAccess = policies[entityType][entitySlug].fields;
}
if (segments.length) {
segments.forEach((segment)=>{
if (fieldAccess[segment]) {
if ('fields' in fieldAccess[segment]) {
fieldAccess = fieldAccess[segment].fields;
} else {
fieldAccess = fieldAccess[segment];
}
}
});
if (!fieldAccess?.read?.permission) {
errors.push({
path: fieldPath
});
}
}
}
if (i > 1) {
// Remove top collection and reverse array
// to work backwards from top
const pathsToQuery = paths.slice(1).reverse();
pathsToQuery.forEach(({ collectionSlug: pathCollectionSlug, path: subPath }, pathToQueryIndex)=>{
// On the "deepest" collection,
// validate query of the relationship
if (pathToQueryIndex === 0) {
promises.push(validateQueryPaths({
collectionConfig: req.payload.collections[pathCollectionSlug].config,
errors,
globalConfig: undefined,
overrideAccess,
policies,
req,
where: {
[subPath]: {
[operator]: val
}
}
}));
}
});
}
}));
await Promise.all(promises);
}
//# sourceMappingURL=validateSearchParams.js.map