@strapi/utils 5.0.0-rc.9 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +409 -178
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +410 -179
- package/dist/index.mjs.map +1 -1
- package/dist/provider-factory.d.ts +1 -1
- package/dist/provider-factory.d.ts.map +1 -1
- package/dist/relations.d.ts +3 -0
- package/dist/relations.d.ts.map +1 -1
- package/dist/sanitize/visitors/remove-restricted-relations.d.ts.map +1 -1
- package/dist/traverse/factory.d.ts +1 -1
- package/dist/traverse/query-fields.d.ts.map +1 -1
- package/dist/traverse/query-populate.d.ts.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validate/utils.d.ts +1 -0
- package/dist/validate/utils.d.ts.map +1 -1
- package/dist/validate/validators.d.ts +19 -7
- package/dist/validate/validators.d.ts.map +1 -1
- package/dist/validate/visitors/throw-restricted-relations.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1335,6 +1335,32 @@ const visitor$7 = ({ schema, key, attribute }, { remove }) => {
|
|
|
1335
1335
|
remove(key);
|
|
1336
1336
|
}
|
|
1337
1337
|
};
|
|
1338
|
+
const MANY_RELATIONS = ["oneToMany", "manyToMany"];
|
|
1339
|
+
const getRelationalFields = (contentType) => {
|
|
1340
|
+
return Object.keys(contentType.attributes).filter((attributeName) => {
|
|
1341
|
+
return contentType.attributes[attributeName].type === "relation";
|
|
1342
|
+
});
|
|
1343
|
+
};
|
|
1344
|
+
const isOneToAny = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "oneToMany"].includes(attribute.relation);
|
|
1345
|
+
const isManyToAny = (attribute) => isRelationalAttribute(attribute) && ["manyToMany", "manyToOne"].includes(attribute.relation);
|
|
1346
|
+
const isAnyToOne = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "manyToOne"].includes(attribute.relation);
|
|
1347
|
+
const isAnyToMany = (attribute) => isRelationalAttribute(attribute) && ["oneToMany", "manyToMany"].includes(attribute.relation);
|
|
1348
|
+
const constants = {
|
|
1349
|
+
MANY_RELATIONS
|
|
1350
|
+
};
|
|
1351
|
+
const VALID_RELATION_ORDERING_KEYS = {
|
|
1352
|
+
strict: fp.isBoolean
|
|
1353
|
+
};
|
|
1354
|
+
const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1355
|
+
__proto__: null,
|
|
1356
|
+
VALID_RELATION_ORDERING_KEYS,
|
|
1357
|
+
constants,
|
|
1358
|
+
getRelationalFields,
|
|
1359
|
+
isAnyToMany,
|
|
1360
|
+
isAnyToOne,
|
|
1361
|
+
isManyToAny,
|
|
1362
|
+
isOneToAny
|
|
1363
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1338
1364
|
const ACTIONS_TO_VERIFY$1 = ["find"];
|
|
1339
1365
|
const { CREATED_BY_ATTRIBUTE: CREATED_BY_ATTRIBUTE$1, UPDATED_BY_ATTRIBUTE: UPDATED_BY_ATTRIBUTE$1 } = constants$1;
|
|
1340
1366
|
const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schema }, { remove, set }) => {
|
|
@@ -1346,19 +1372,57 @@ const removeRestrictedRelations = (auth) => async ({ data, key, attribute, schem
|
|
|
1346
1372
|
return;
|
|
1347
1373
|
}
|
|
1348
1374
|
const handleMorphRelation = async () => {
|
|
1349
|
-
const
|
|
1350
|
-
|
|
1375
|
+
const elements = data[key];
|
|
1376
|
+
if ("connect" in elements || "set" in elements || "disconnect" in elements) {
|
|
1377
|
+
const newValue = {};
|
|
1378
|
+
const connect = await handleMorphElements(elements.connect || []);
|
|
1379
|
+
const relSet = await handleMorphElements(elements.set || []);
|
|
1380
|
+
const disconnect = await handleMorphElements(elements.disconnect || []);
|
|
1381
|
+
if (connect.length > 0) {
|
|
1382
|
+
newValue.connect = connect;
|
|
1383
|
+
}
|
|
1384
|
+
if (relSet.length > 0) {
|
|
1385
|
+
newValue.set = relSet;
|
|
1386
|
+
}
|
|
1387
|
+
if (disconnect.length > 0) {
|
|
1388
|
+
newValue.disconnect = disconnect;
|
|
1389
|
+
}
|
|
1390
|
+
if ("options" in elements && typeof elements.options === "object" && elements.options !== null) {
|
|
1391
|
+
const filteredOptions = {};
|
|
1392
|
+
Object.keys(elements.options).forEach((key2) => {
|
|
1393
|
+
const validator = VALID_RELATION_ORDERING_KEYS[key2];
|
|
1394
|
+
if (validator && validator(elements.options[key2])) {
|
|
1395
|
+
filteredOptions[key2] = elements.options[key2];
|
|
1396
|
+
}
|
|
1397
|
+
});
|
|
1398
|
+
newValue.options = filteredOptions;
|
|
1399
|
+
}
|
|
1400
|
+
set(key, newValue);
|
|
1401
|
+
} else {
|
|
1402
|
+
const newMorphValue = await handleMorphElements(elements);
|
|
1403
|
+
if (newMorphValue.length === 0) {
|
|
1404
|
+
remove(key);
|
|
1405
|
+
} else {
|
|
1406
|
+
set(key, newMorphValue);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
};
|
|
1410
|
+
const handleMorphElements = async (elements) => {
|
|
1411
|
+
const allowedElements = [];
|
|
1412
|
+
if (!fp.isArray(elements)) {
|
|
1413
|
+
return allowedElements;
|
|
1414
|
+
}
|
|
1415
|
+
for (const element of elements) {
|
|
1416
|
+
if (!fp.isObject(element) || !("__type" in element)) {
|
|
1417
|
+
continue;
|
|
1418
|
+
}
|
|
1351
1419
|
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${element.__type}.${action}`);
|
|
1352
1420
|
const isAllowed = await hasAccessToSomeScopes$1(scopes, auth);
|
|
1353
1421
|
if (isAllowed) {
|
|
1354
|
-
|
|
1422
|
+
allowedElements.push(element);
|
|
1355
1423
|
}
|
|
1356
1424
|
}
|
|
1357
|
-
|
|
1358
|
-
remove(key);
|
|
1359
|
-
} else {
|
|
1360
|
-
set(key, newMorphValue);
|
|
1361
|
-
}
|
|
1425
|
+
return allowedElements;
|
|
1362
1426
|
};
|
|
1363
1427
|
const handleRegularRelation = async () => {
|
|
1364
1428
|
const scopes = ACTIONS_TO_VERIFY$1.map((action) => `${attribute.target}.${action}`);
|
|
@@ -1884,10 +1948,17 @@ const populate = traverseFactory().intercept(isStringArray$1, async (visitor2, o
|
|
|
1884
1948
|
}
|
|
1885
1949
|
});
|
|
1886
1950
|
const traverseQueryPopulate = fp.curry(populate.traverse);
|
|
1887
|
-
const isStringArray = (value) =>
|
|
1951
|
+
const isStringArray = (value) => {
|
|
1952
|
+
return fp.isArray(value) && value.every(fp.isString);
|
|
1953
|
+
};
|
|
1888
1954
|
const fields = traverseFactory().intercept(isStringArray, async (visitor2, options, fields2, { recurse }) => {
|
|
1889
1955
|
return Promise.all(fields2.map((field) => recurse(visitor2, options, field)));
|
|
1890
|
-
}).intercept(
|
|
1956
|
+
}).intercept(
|
|
1957
|
+
(value) => fp.isString(value) && value.includes(","),
|
|
1958
|
+
(visitor2, options, fields2, { recurse }) => {
|
|
1959
|
+
return Promise.all(fields2.split(",").map((field) => recurse(visitor2, options, field)));
|
|
1960
|
+
}
|
|
1961
|
+
).intercept((value) => fp.eq("*", value), fp.constant("*")).parse(fp.isString, () => ({
|
|
1891
1962
|
transform: fp.trim,
|
|
1892
1963
|
remove(key, data) {
|
|
1893
1964
|
return data === key ? void 0 : data;
|
|
@@ -2188,6 +2259,15 @@ const throwInvalidKey = ({ key, path }) => {
|
|
|
2188
2259
|
path
|
|
2189
2260
|
});
|
|
2190
2261
|
};
|
|
2262
|
+
const asyncCurry = (fn) => {
|
|
2263
|
+
const curried = (...args) => {
|
|
2264
|
+
if (args.length >= fn.length) {
|
|
2265
|
+
return fn(...args);
|
|
2266
|
+
}
|
|
2267
|
+
return (...moreArgs) => curried(...args, ...moreArgs);
|
|
2268
|
+
};
|
|
2269
|
+
return curried;
|
|
2270
|
+
};
|
|
2191
2271
|
const visitor$3 = ({ key, attribute, path }) => {
|
|
2192
2272
|
if (attribute?.type === "password") {
|
|
2193
2273
|
throwInvalidKey({ key, path: path.attribute });
|
|
@@ -2213,7 +2293,40 @@ const throwRestrictedRelations = (auth) => async ({ data, key, attribute, schema
|
|
|
2213
2293
|
return;
|
|
2214
2294
|
}
|
|
2215
2295
|
const handleMorphRelation = async () => {
|
|
2216
|
-
|
|
2296
|
+
const elements = data[key];
|
|
2297
|
+
if ("connect" in elements || "set" in elements || "disconnect" in elements || "options" in elements) {
|
|
2298
|
+
await handleMorphElements(elements.connect || []);
|
|
2299
|
+
await handleMorphElements(elements.set || []);
|
|
2300
|
+
await handleMorphElements(elements.disconnect || []);
|
|
2301
|
+
if ("options" in elements) {
|
|
2302
|
+
if (elements.options === null || elements.options === void 0) {
|
|
2303
|
+
return;
|
|
2304
|
+
}
|
|
2305
|
+
if (typeof elements.options !== "object") {
|
|
2306
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2307
|
+
}
|
|
2308
|
+
const optionKeys = Object.keys(elements.options);
|
|
2309
|
+
for (const key2 of optionKeys) {
|
|
2310
|
+
if (!(key2 in VALID_RELATION_ORDERING_KEYS)) {
|
|
2311
|
+
throwInvalidKey({ key: key2, path: path.attribute });
|
|
2312
|
+
}
|
|
2313
|
+
if (!VALID_RELATION_ORDERING_KEYS[key2](elements.options[key2])) {
|
|
2314
|
+
throwInvalidKey({ key: key2, path: path.attribute });
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
} else {
|
|
2319
|
+
await handleMorphElements(elements);
|
|
2320
|
+
}
|
|
2321
|
+
};
|
|
2322
|
+
const handleMorphElements = async (elements) => {
|
|
2323
|
+
if (!fp.isArray(elements)) {
|
|
2324
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2325
|
+
}
|
|
2326
|
+
for (const element of elements) {
|
|
2327
|
+
if (!fp.isObject(element) || !("__type" in element)) {
|
|
2328
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2329
|
+
}
|
|
2217
2330
|
const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);
|
|
2218
2331
|
const isAllowed = await hasAccessToSomeScopes(scopes, auth);
|
|
2219
2332
|
if (!isAllowed) {
|
|
@@ -2353,154 +2466,294 @@ const throwPasswords = (ctx) => async (entity) => {
|
|
|
2353
2466
|
}
|
|
2354
2467
|
return traverseEntity$1(visitor$3, ctx, entity);
|
|
2355
2468
|
};
|
|
2356
|
-
const
|
|
2357
|
-
|
|
2358
|
-
|
|
2469
|
+
const FILTER_TRAVERSALS = [
|
|
2470
|
+
"nonAttributesOperators",
|
|
2471
|
+
"dynamicZones",
|
|
2472
|
+
"morphRelations",
|
|
2473
|
+
"passwords",
|
|
2474
|
+
"private"
|
|
2475
|
+
];
|
|
2476
|
+
const validateFilters = asyncCurry(
|
|
2477
|
+
async (ctx, filters2, include) => {
|
|
2478
|
+
if (!ctx.schema) {
|
|
2479
|
+
throw new Error("Missing schema in defaultValidateFilters");
|
|
2480
|
+
}
|
|
2481
|
+
const functionsToApply = [];
|
|
2482
|
+
if (include.includes("nonAttributesOperators")) {
|
|
2483
|
+
functionsToApply.push(
|
|
2484
|
+
traverseQueryFilters(({ key, attribute, path }) => {
|
|
2485
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2488
|
+
const isAttribute = !!attribute;
|
|
2489
|
+
if (!isAttribute && !isOperator(key)) {
|
|
2490
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2491
|
+
}
|
|
2492
|
+
}, ctx)
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
if (include.includes("dynamicZones")) {
|
|
2496
|
+
functionsToApply.push(traverseQueryFilters(visitor, ctx));
|
|
2497
|
+
}
|
|
2498
|
+
if (include.includes("morphRelations")) {
|
|
2499
|
+
functionsToApply.push(traverseQueryFilters(visitor$1, ctx));
|
|
2500
|
+
}
|
|
2501
|
+
if (include.includes("passwords")) {
|
|
2502
|
+
functionsToApply.push(traverseQueryFilters(visitor$3, ctx));
|
|
2503
|
+
}
|
|
2504
|
+
if (include.includes("private")) {
|
|
2505
|
+
functionsToApply.push(traverseQueryFilters(visitor$2, ctx));
|
|
2506
|
+
}
|
|
2507
|
+
if (functionsToApply.length === 0) {
|
|
2508
|
+
return filters2;
|
|
2509
|
+
}
|
|
2510
|
+
return pipe(...functionsToApply)(filters2);
|
|
2359
2511
|
}
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2364
|
-
return;
|
|
2365
|
-
}
|
|
2366
|
-
const isAttribute = !!attribute;
|
|
2367
|
-
if (!isAttribute && !isOperator(key)) {
|
|
2368
|
-
throwInvalidKey({ key, path: path.attribute });
|
|
2369
|
-
}
|
|
2370
|
-
}, ctx),
|
|
2371
|
-
// dynamic zones from filters
|
|
2372
|
-
traverseQueryFilters(visitor, ctx),
|
|
2373
|
-
// morphTo relations from filters; because you can't have deep filtering on morph relations
|
|
2374
|
-
traverseQueryFilters(visitor$1, ctx),
|
|
2375
|
-
// passwords from filters
|
|
2376
|
-
traverseQueryFilters(visitor$3, ctx),
|
|
2377
|
-
// private from filters
|
|
2378
|
-
traverseQueryFilters(visitor$2, ctx)
|
|
2379
|
-
// we allow empty objects to validate and only sanitize them out, so that users may write "lazy" queries without checking their params exist
|
|
2380
|
-
)(filters2);
|
|
2512
|
+
);
|
|
2513
|
+
const defaultValidateFilters = asyncCurry(async (ctx, filters2) => {
|
|
2514
|
+
return validateFilters(ctx, filters2, FILTER_TRAVERSALS);
|
|
2381
2515
|
});
|
|
2382
|
-
const
|
|
2383
|
-
|
|
2384
|
-
|
|
2516
|
+
const SORT_TRAVERSALS = [
|
|
2517
|
+
"nonAttributesOperators",
|
|
2518
|
+
"dynamicZones",
|
|
2519
|
+
"morphRelations",
|
|
2520
|
+
"passwords",
|
|
2521
|
+
"private",
|
|
2522
|
+
"nonScalarEmptyKeys"
|
|
2523
|
+
];
|
|
2524
|
+
const validateSort = asyncCurry(
|
|
2525
|
+
async (ctx, sort2, include) => {
|
|
2526
|
+
if (!ctx.schema) {
|
|
2527
|
+
throw new Error("Missing schema in defaultValidateSort");
|
|
2528
|
+
}
|
|
2529
|
+
const functionsToApply = [];
|
|
2530
|
+
if (include.includes("nonAttributesOperators")) {
|
|
2531
|
+
functionsToApply.push(
|
|
2532
|
+
traverseQuerySort(({ key, attribute, path }) => {
|
|
2533
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2534
|
+
return;
|
|
2535
|
+
}
|
|
2536
|
+
if (!attribute) {
|
|
2537
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2538
|
+
}
|
|
2539
|
+
}, ctx)
|
|
2540
|
+
);
|
|
2541
|
+
}
|
|
2542
|
+
if (include.includes("dynamicZones")) {
|
|
2543
|
+
functionsToApply.push(traverseQuerySort(visitor, ctx));
|
|
2544
|
+
}
|
|
2545
|
+
if (include.includes("morphRelations")) {
|
|
2546
|
+
functionsToApply.push(traverseQuerySort(visitor$1, ctx));
|
|
2547
|
+
}
|
|
2548
|
+
if (include.includes("passwords")) {
|
|
2549
|
+
functionsToApply.push(traverseQuerySort(visitor$3, ctx));
|
|
2550
|
+
}
|
|
2551
|
+
if (include.includes("private")) {
|
|
2552
|
+
functionsToApply.push(traverseQuerySort(visitor$2, ctx));
|
|
2553
|
+
}
|
|
2554
|
+
if (include.includes("nonScalarEmptyKeys")) {
|
|
2555
|
+
functionsToApply.push(
|
|
2556
|
+
traverseQuerySort(({ key, attribute, value, path }) => {
|
|
2557
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
if (!isScalarAttribute(attribute) && fp.isEmpty(value)) {
|
|
2561
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2562
|
+
}
|
|
2563
|
+
}, ctx)
|
|
2564
|
+
);
|
|
2565
|
+
}
|
|
2566
|
+
if (functionsToApply.length === 0) {
|
|
2567
|
+
return sort2;
|
|
2568
|
+
}
|
|
2569
|
+
return pipe(...functionsToApply)(sort2);
|
|
2385
2570
|
}
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2390
|
-
return;
|
|
2391
|
-
}
|
|
2392
|
-
if (!attribute) {
|
|
2393
|
-
throwInvalidKey({ key, path: path.attribute });
|
|
2394
|
-
}
|
|
2395
|
-
}, ctx),
|
|
2396
|
-
// dynamic zones from sort
|
|
2397
|
-
traverseQuerySort(visitor, ctx),
|
|
2398
|
-
// morphTo relations from sort
|
|
2399
|
-
traverseQuerySort(visitor$1, ctx),
|
|
2400
|
-
// private from sort
|
|
2401
|
-
traverseQuerySort(visitor$2, ctx),
|
|
2402
|
-
// passwords from filters
|
|
2403
|
-
traverseQuerySort(visitor$3, ctx),
|
|
2404
|
-
// keys for empty non-scalar values
|
|
2405
|
-
traverseQuerySort(({ key, attribute, value, path }) => {
|
|
2406
|
-
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2407
|
-
return;
|
|
2408
|
-
}
|
|
2409
|
-
if (!isScalarAttribute(attribute) && fp.isEmpty(value)) {
|
|
2410
|
-
throwInvalidKey({ key, path: path.attribute });
|
|
2411
|
-
}
|
|
2412
|
-
}, ctx)
|
|
2413
|
-
)(sort2);
|
|
2571
|
+
);
|
|
2572
|
+
const defaultValidateSort = asyncCurry(async (ctx, sort2) => {
|
|
2573
|
+
return validateSort(ctx, sort2, SORT_TRAVERSALS);
|
|
2414
2574
|
});
|
|
2415
|
-
const
|
|
2416
|
-
|
|
2417
|
-
|
|
2575
|
+
const FIELDS_TRAVERSALS = ["scalarAttributes", "privateFields", "passwordFields"];
|
|
2576
|
+
const validateFields = asyncCurry(
|
|
2577
|
+
async (ctx, fields2, include) => {
|
|
2578
|
+
if (!ctx.schema) {
|
|
2579
|
+
throw new Error("Missing schema in defaultValidateFields");
|
|
2580
|
+
}
|
|
2581
|
+
const functionsToApply = [];
|
|
2582
|
+
if (include.includes("scalarAttributes")) {
|
|
2583
|
+
functionsToApply.push(
|
|
2584
|
+
traverseQueryFields(({ key, attribute, path }) => {
|
|
2585
|
+
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2586
|
+
return;
|
|
2587
|
+
}
|
|
2588
|
+
if (fp.isNil(attribute) || !isScalarAttribute(attribute)) {
|
|
2589
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2590
|
+
}
|
|
2591
|
+
}, ctx)
|
|
2592
|
+
);
|
|
2593
|
+
}
|
|
2594
|
+
if (include.includes("privateFields")) {
|
|
2595
|
+
functionsToApply.push(traverseQueryFields(visitor$2, ctx));
|
|
2596
|
+
}
|
|
2597
|
+
if (include.includes("passwordFields")) {
|
|
2598
|
+
functionsToApply.push(traverseQueryFields(visitor$3, ctx));
|
|
2599
|
+
}
|
|
2600
|
+
if (functionsToApply.length === 0) {
|
|
2601
|
+
return fields2;
|
|
2602
|
+
}
|
|
2603
|
+
return pipe(...functionsToApply)(fields2);
|
|
2418
2604
|
}
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
if ([ID_ATTRIBUTE$1, DOC_ID_ATTRIBUTE$1].includes(key)) {
|
|
2423
|
-
return;
|
|
2424
|
-
}
|
|
2425
|
-
if (fp.isNil(attribute) || !isScalarAttribute(attribute)) {
|
|
2426
|
-
throwInvalidKey({ key, path: path.attribute });
|
|
2427
|
-
}
|
|
2428
|
-
}, ctx),
|
|
2429
|
-
// private fields
|
|
2430
|
-
traverseQueryFields(visitor$2, ctx),
|
|
2431
|
-
// password fields
|
|
2432
|
-
traverseQueryFields(visitor$3, ctx)
|
|
2433
|
-
)(fields2);
|
|
2605
|
+
);
|
|
2606
|
+
const defaultValidateFields = asyncCurry(async (ctx, fields2) => {
|
|
2607
|
+
return validateFields(ctx, fields2, FIELDS_TRAVERSALS);
|
|
2434
2608
|
});
|
|
2435
|
-
const
|
|
2609
|
+
const POPULATE_TRAVERSALS = ["nonAttributesOperators", "private"];
|
|
2610
|
+
const validatePopulate = asyncCurry(
|
|
2611
|
+
async (ctx, populate2, includes) => {
|
|
2612
|
+
if (!ctx.schema) {
|
|
2613
|
+
throw new Error("Missing schema in defaultValidatePopulate");
|
|
2614
|
+
}
|
|
2615
|
+
const functionsToApply = [];
|
|
2616
|
+
functionsToApply.push(
|
|
2617
|
+
traverseQueryPopulate(async ({ key, path, value, schema, attribute, getModel }, { set }) => {
|
|
2618
|
+
if (attribute) {
|
|
2619
|
+
const isPopulatableAttribute = ["relation", "dynamiczone", "component", "media"].includes(
|
|
2620
|
+
attribute.type
|
|
2621
|
+
);
|
|
2622
|
+
if (!isPopulatableAttribute) {
|
|
2623
|
+
throwInvalidKey({ key, path: path.raw });
|
|
2624
|
+
}
|
|
2625
|
+
return;
|
|
2626
|
+
}
|
|
2627
|
+
if (key === "on") {
|
|
2628
|
+
if (!fp.isObject(value)) {
|
|
2629
|
+
return throwInvalidKey({ key, path: path.raw });
|
|
2630
|
+
}
|
|
2631
|
+
const targets = Object.keys(value);
|
|
2632
|
+
for (const target of targets) {
|
|
2633
|
+
const model = getModel(target);
|
|
2634
|
+
if (!model) {
|
|
2635
|
+
throwInvalidKey({ key: target, path: `${path.raw}.${target}` });
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
return;
|
|
2639
|
+
}
|
|
2640
|
+
if (key === "" && value === "*") {
|
|
2641
|
+
return;
|
|
2642
|
+
}
|
|
2643
|
+
if (key === "count") {
|
|
2644
|
+
try {
|
|
2645
|
+
parseType({ type: "boolean", value });
|
|
2646
|
+
return;
|
|
2647
|
+
} catch {
|
|
2648
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
try {
|
|
2652
|
+
parseType({ type: "boolean", value: key });
|
|
2653
|
+
return;
|
|
2654
|
+
} catch {
|
|
2655
|
+
}
|
|
2656
|
+
if (key === "sort") {
|
|
2657
|
+
set(
|
|
2658
|
+
key,
|
|
2659
|
+
await validateSort(
|
|
2660
|
+
{
|
|
2661
|
+
schema,
|
|
2662
|
+
getModel
|
|
2663
|
+
},
|
|
2664
|
+
value,
|
|
2665
|
+
// pass the sort value
|
|
2666
|
+
includes?.sort || SORT_TRAVERSALS
|
|
2667
|
+
)
|
|
2668
|
+
);
|
|
2669
|
+
return;
|
|
2670
|
+
}
|
|
2671
|
+
if (key === "filters") {
|
|
2672
|
+
set(
|
|
2673
|
+
key,
|
|
2674
|
+
await validateFilters(
|
|
2675
|
+
{
|
|
2676
|
+
schema,
|
|
2677
|
+
getModel
|
|
2678
|
+
},
|
|
2679
|
+
value,
|
|
2680
|
+
// pass the filters value
|
|
2681
|
+
includes?.filters || FILTER_TRAVERSALS
|
|
2682
|
+
)
|
|
2683
|
+
);
|
|
2684
|
+
return;
|
|
2685
|
+
}
|
|
2686
|
+
if (key === "fields") {
|
|
2687
|
+
set(
|
|
2688
|
+
key,
|
|
2689
|
+
await validateFields(
|
|
2690
|
+
{
|
|
2691
|
+
schema,
|
|
2692
|
+
getModel
|
|
2693
|
+
},
|
|
2694
|
+
value,
|
|
2695
|
+
// pass the fields value
|
|
2696
|
+
includes?.fields || FIELDS_TRAVERSALS
|
|
2697
|
+
)
|
|
2698
|
+
);
|
|
2699
|
+
return;
|
|
2700
|
+
}
|
|
2701
|
+
if (key === "populate") {
|
|
2702
|
+
set(
|
|
2703
|
+
key,
|
|
2704
|
+
await validatePopulate(
|
|
2705
|
+
{
|
|
2706
|
+
schema,
|
|
2707
|
+
getModel
|
|
2708
|
+
},
|
|
2709
|
+
value,
|
|
2710
|
+
// pass the nested populate value
|
|
2711
|
+
includes
|
|
2712
|
+
// pass down the same includes object
|
|
2713
|
+
)
|
|
2714
|
+
);
|
|
2715
|
+
return;
|
|
2716
|
+
}
|
|
2717
|
+
if (includes?.populate?.includes("nonAttributesOperators")) {
|
|
2718
|
+
throwInvalidKey({ key, path: path.attribute });
|
|
2719
|
+
}
|
|
2720
|
+
}, ctx)
|
|
2721
|
+
);
|
|
2722
|
+
if (includes?.populate?.includes("private")) {
|
|
2723
|
+
functionsToApply.push(traverseQueryPopulate(visitor$2, ctx));
|
|
2724
|
+
}
|
|
2725
|
+
if (functionsToApply.length === 0) {
|
|
2726
|
+
return populate2;
|
|
2727
|
+
}
|
|
2728
|
+
return pipe(...functionsToApply)(populate2);
|
|
2729
|
+
}
|
|
2730
|
+
);
|
|
2731
|
+
const defaultValidatePopulate = asyncCurry(async (ctx, populate2) => {
|
|
2436
2732
|
if (!ctx.schema) {
|
|
2437
2733
|
throw new Error("Missing schema in defaultValidatePopulate");
|
|
2438
2734
|
}
|
|
2439
|
-
return
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
set(
|
|
2446
|
-
key,
|
|
2447
|
-
await defaultValidateSort(
|
|
2448
|
-
{
|
|
2449
|
-
schema,
|
|
2450
|
-
getModel
|
|
2451
|
-
},
|
|
2452
|
-
value
|
|
2453
|
-
)
|
|
2454
|
-
);
|
|
2455
|
-
}
|
|
2456
|
-
if (key === "filters") {
|
|
2457
|
-
set(
|
|
2458
|
-
key,
|
|
2459
|
-
await defaultValidateFilters(
|
|
2460
|
-
{
|
|
2461
|
-
schema,
|
|
2462
|
-
getModel
|
|
2463
|
-
},
|
|
2464
|
-
value
|
|
2465
|
-
)
|
|
2466
|
-
);
|
|
2467
|
-
}
|
|
2468
|
-
if (key === "fields") {
|
|
2469
|
-
set(
|
|
2470
|
-
key,
|
|
2471
|
-
await defaultValidateFields(
|
|
2472
|
-
{
|
|
2473
|
-
schema,
|
|
2474
|
-
getModel
|
|
2475
|
-
},
|
|
2476
|
-
value
|
|
2477
|
-
)
|
|
2478
|
-
);
|
|
2479
|
-
}
|
|
2480
|
-
if (key === "populate") {
|
|
2481
|
-
set(
|
|
2482
|
-
key,
|
|
2483
|
-
await defaultValidatePopulate(
|
|
2484
|
-
{
|
|
2485
|
-
schema,
|
|
2486
|
-
getModel
|
|
2487
|
-
},
|
|
2488
|
-
value
|
|
2489
|
-
)
|
|
2490
|
-
);
|
|
2491
|
-
}
|
|
2492
|
-
}, ctx),
|
|
2493
|
-
// Remove private fields
|
|
2494
|
-
traverseQueryPopulate(visitor$2, ctx)
|
|
2495
|
-
)(populate2);
|
|
2735
|
+
return validatePopulate(ctx, populate2, {
|
|
2736
|
+
filters: FILTER_TRAVERSALS,
|
|
2737
|
+
sort: SORT_TRAVERSALS,
|
|
2738
|
+
fields: FIELDS_TRAVERSALS,
|
|
2739
|
+
populate: POPULATE_TRAVERSALS
|
|
2740
|
+
});
|
|
2496
2741
|
});
|
|
2497
2742
|
const validators = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2498
2743
|
__proto__: null,
|
|
2744
|
+
FIELDS_TRAVERSALS,
|
|
2745
|
+
FILTER_TRAVERSALS,
|
|
2746
|
+
POPULATE_TRAVERSALS,
|
|
2747
|
+
SORT_TRAVERSALS,
|
|
2499
2748
|
defaultValidateFields,
|
|
2500
2749
|
defaultValidateFilters,
|
|
2501
2750
|
defaultValidatePopulate,
|
|
2502
2751
|
defaultValidateSort,
|
|
2503
|
-
throwPasswords
|
|
2752
|
+
throwPasswords,
|
|
2753
|
+
validateFields,
|
|
2754
|
+
validateFilters,
|
|
2755
|
+
validatePopulate,
|
|
2756
|
+
validateSort
|
|
2504
2757
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2505
2758
|
const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE } = constants$1;
|
|
2506
2759
|
const createAPIValidators = (opts) => {
|
|
@@ -2555,24 +2808,24 @@ const createAPIValidators = (opts) => {
|
|
|
2555
2808
|
}
|
|
2556
2809
|
const { filters: filters2, sort: sort2, fields: fields2, populate: populate2 } = query;
|
|
2557
2810
|
if (filters2) {
|
|
2558
|
-
await
|
|
2811
|
+
await validateFilters2(filters2, schema, { auth });
|
|
2559
2812
|
}
|
|
2560
2813
|
if (sort2) {
|
|
2561
|
-
await
|
|
2814
|
+
await validateSort2(sort2, schema, { auth });
|
|
2562
2815
|
}
|
|
2563
2816
|
if (fields2) {
|
|
2564
|
-
await
|
|
2817
|
+
await validateFields2(fields2, schema);
|
|
2565
2818
|
}
|
|
2566
2819
|
if (populate2 && populate2 !== "*") {
|
|
2567
|
-
await
|
|
2820
|
+
await validatePopulate2(populate2, schema);
|
|
2568
2821
|
}
|
|
2569
2822
|
};
|
|
2570
|
-
const
|
|
2823
|
+
const validateFilters2 = async (filters2, schema, { auth } = {}) => {
|
|
2571
2824
|
if (!schema) {
|
|
2572
2825
|
throw new Error("Missing schema in validateFilters");
|
|
2573
2826
|
}
|
|
2574
2827
|
if (fp.isArray(filters2)) {
|
|
2575
|
-
await Promise.all(filters2.map((filter) =>
|
|
2828
|
+
await Promise.all(filters2.map((filter) => validateFilters2(filter, schema, { auth })));
|
|
2576
2829
|
return;
|
|
2577
2830
|
}
|
|
2578
2831
|
const transforms = [defaultValidateFilters({ schema, getModel })];
|
|
@@ -2594,7 +2847,7 @@ const createAPIValidators = (opts) => {
|
|
|
2594
2847
|
throw e;
|
|
2595
2848
|
}
|
|
2596
2849
|
};
|
|
2597
|
-
const
|
|
2850
|
+
const validateSort2 = async (sort2, schema, { auth } = {}) => {
|
|
2598
2851
|
if (!schema) {
|
|
2599
2852
|
throw new Error("Missing schema in validateSort");
|
|
2600
2853
|
}
|
|
@@ -2617,7 +2870,7 @@ const createAPIValidators = (opts) => {
|
|
|
2617
2870
|
throw e;
|
|
2618
2871
|
}
|
|
2619
2872
|
};
|
|
2620
|
-
const
|
|
2873
|
+
const validateFields2 = async (fields2, schema) => {
|
|
2621
2874
|
if (!schema) {
|
|
2622
2875
|
throw new Error("Missing schema in validateFields");
|
|
2623
2876
|
}
|
|
@@ -2632,7 +2885,7 @@ const createAPIValidators = (opts) => {
|
|
|
2632
2885
|
throw e;
|
|
2633
2886
|
}
|
|
2634
2887
|
};
|
|
2635
|
-
const
|
|
2888
|
+
const validatePopulate2 = async (populate2, schema, { auth } = {}) => {
|
|
2636
2889
|
if (!schema) {
|
|
2637
2890
|
throw new Error("Missing schema in sanitizePopulate");
|
|
2638
2891
|
}
|
|
@@ -2658,10 +2911,10 @@ const createAPIValidators = (opts) => {
|
|
|
2658
2911
|
return {
|
|
2659
2912
|
input: validateInput,
|
|
2660
2913
|
query: validateQuery,
|
|
2661
|
-
filters:
|
|
2662
|
-
sort:
|
|
2663
|
-
fields:
|
|
2664
|
-
populate:
|
|
2914
|
+
filters: validateFilters2,
|
|
2915
|
+
sort: validateSort2,
|
|
2916
|
+
fields: validateFields2,
|
|
2917
|
+
populate: validatePopulate2
|
|
2665
2918
|
};
|
|
2666
2919
|
};
|
|
2667
2920
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -3118,28 +3371,6 @@ const yup = /* @__PURE__ */ _mergeNamespaces({
|
|
|
3118
3371
|
StrapiIDSchema,
|
|
3119
3372
|
strapiID
|
|
3120
3373
|
}, [yup__namespace]);
|
|
3121
|
-
const MANY_RELATIONS = ["oneToMany", "manyToMany"];
|
|
3122
|
-
const getRelationalFields = (contentType) => {
|
|
3123
|
-
return Object.keys(contentType.attributes).filter((attributeName) => {
|
|
3124
|
-
return contentType.attributes[attributeName].type === "relation";
|
|
3125
|
-
});
|
|
3126
|
-
};
|
|
3127
|
-
const isOneToAny = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "oneToMany"].includes(attribute.relation);
|
|
3128
|
-
const isManyToAny = (attribute) => isRelationalAttribute(attribute) && ["manyToMany", "manyToOne"].includes(attribute.relation);
|
|
3129
|
-
const isAnyToOne = (attribute) => isRelationalAttribute(attribute) && ["oneToOne", "manyToOne"].includes(attribute.relation);
|
|
3130
|
-
const isAnyToMany = (attribute) => isRelationalAttribute(attribute) && ["oneToMany", "manyToMany"].includes(attribute.relation);
|
|
3131
|
-
const constants = {
|
|
3132
|
-
MANY_RELATIONS
|
|
3133
|
-
};
|
|
3134
|
-
const relations = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3135
|
-
__proto__: null,
|
|
3136
|
-
constants,
|
|
3137
|
-
getRelationalFields,
|
|
3138
|
-
isAnyToMany,
|
|
3139
|
-
isAnyToOne,
|
|
3140
|
-
isManyToAny,
|
|
3141
|
-
isOneToAny
|
|
3142
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
3143
3374
|
const validateZod = (schema) => (data) => {
|
|
3144
3375
|
try {
|
|
3145
3376
|
return schema.parse(data);
|