@web-ts-toolkit/access-router 0.56.0 → 0.58.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/README.md +177 -120
- package/advanced.d.mts +1 -1
- package/advanced.d.ts +1 -1
- package/advanced.js +95 -66
- package/advanced.mjs +62 -33
- package/index.d.mts +2 -2
- package/index.d.ts +2 -2
- package/index.js +965 -623
- package/index.mjs +703 -361
- package/llms.txt +2 -2
- package/package.json +3 -3
- package/{parsers-BXKoUKMa.d.mts → parsers-CngKnVjW.d.mts} +65 -37
- package/{parsers-BXKoUKMa.d.ts → parsers-CngKnVjW.d.ts} +65 -37
package/index.js
CHANGED
|
@@ -2161,9 +2161,34 @@ var init_field_catalog = __esm({
|
|
|
2161
2161
|
}
|
|
2162
2162
|
});
|
|
2163
2163
|
|
|
2164
|
+
// src/acl/populate-target-configuration.ts
|
|
2165
|
+
function capturePopulateTargetConfiguration(runtime, modelName, source, proposedOptions) {
|
|
2166
|
+
const label = `Populate target "${modelName}" for ${source}`;
|
|
2167
|
+
if (!proposedOptions && !runtime.hasModel(modelName))
|
|
2168
|
+
authorizationError(
|
|
2169
|
+
`${label} must be configured first in this runtime; register its Mongoose model and setModelOptions with an object permissionSchema`
|
|
2170
|
+
);
|
|
2171
|
+
const model = runtime.getModelInstance(modelName);
|
|
2172
|
+
if (!model) authorizationError(`${label} requires an actual registered Mongoose model in this runtime`);
|
|
2173
|
+
const options = proposedOptions ?? runtime.getModelOptions(modelName);
|
|
2174
|
+
const permissionSchema = options.permissionSchema === void 0 ? runtime.getDefaultModelOption("permissionSchema") : options.permissionSchema;
|
|
2175
|
+
if (!(0, import_utils15.isPlainObject)(permissionSchema))
|
|
2176
|
+
authorizationError(
|
|
2177
|
+
`${label} requires an effective object permissionSchema; configure the model or runtime model defaults ({} explicitly closes business fields)`
|
|
2178
|
+
);
|
|
2179
|
+
return { model, options: { ...options, permissionSchema } };
|
|
2180
|
+
}
|
|
2181
|
+
var import_utils15;
|
|
2182
|
+
var init_populate_target_configuration = __esm({
|
|
2183
|
+
"src/acl/populate-target-configuration.ts"() {
|
|
2184
|
+
import_utils15 = require("@web-ts-toolkit/utils");
|
|
2185
|
+
init_authorization_snapshot();
|
|
2186
|
+
}
|
|
2187
|
+
});
|
|
2188
|
+
|
|
2164
2189
|
// src/acl/virtual-populate-dependencies.ts
|
|
2165
2190
|
function record(value, label) {
|
|
2166
|
-
if (!(0,
|
|
2191
|
+
if (!(0, import_utils16.isPlainObject)(value)) return fail(label, "entries must be plain { path, select? } objects");
|
|
2167
2192
|
for (const key of Reflect.ownKeys(value)) {
|
|
2168
2193
|
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
2169
2194
|
if (typeof key !== "string" || !property.enumerable || !("value" in property))
|
|
@@ -2252,7 +2277,8 @@ function normalizeSelection(select, catalog, label) {
|
|
|
2252
2277
|
};
|
|
2253
2278
|
}
|
|
2254
2279
|
function captureVirtualPopulateDependencies(runtime, modelName, options, globalOptions = runtime.getGlobalOptions()) {
|
|
2255
|
-
const
|
|
2280
|
+
const requireOperationAccessForPopulateDependencies = globalOptions.requireOperationAccessForPopulateDependencies !== false;
|
|
2281
|
+
const requireOperationAccessForPopulateQueries = globalOptions.requireOperationAccessForPopulateQueries !== false;
|
|
2256
2282
|
const model = runtime.getModelInstance(modelName);
|
|
2257
2283
|
const targets = /* @__PURE__ */ new Map();
|
|
2258
2284
|
const scopes = [];
|
|
@@ -2292,16 +2318,23 @@ function captureVirtualPopulateDependencies(runtime, modelName, options, globalO
|
|
|
2292
2318
|
label,
|
|
2293
2319
|
`target "${ref}" requires a registered same-connection non-discriminator ObjectId model bound to the source ref`
|
|
2294
2320
|
);
|
|
2295
|
-
const
|
|
2321
|
+
const { options: targetOptions } = capturePopulateTargetConfiguration(
|
|
2322
|
+
runtime,
|
|
2323
|
+
ref,
|
|
2324
|
+
`dependsOnPopulate virtual "${label}"`,
|
|
2325
|
+
ref === modelName ? options : void 0
|
|
2326
|
+
);
|
|
2296
2327
|
const defaults = runtime.getDefaultModelOptions();
|
|
2297
|
-
const readOption = (key) => resolveNestedOption((path2, fallback) => (0,
|
|
2328
|
+
const readOption = (key) => resolveNestedOption((path2, fallback) => (0, import_utils16.get)(targetOptions, path2, fallback), key, (0, import_utils16.get)(defaults, key));
|
|
2298
2329
|
const documentPermissionField = targetOptions.documentPermissionField ?? defaults.documentPermissionField;
|
|
2299
2330
|
const catalog = captureAuthorizationFieldCatalog(targetModel.schema, void 0, documentPermissionField);
|
|
2300
2331
|
const configuration = copyAuthorizationValue(
|
|
2301
2332
|
{
|
|
2302
2333
|
catalog,
|
|
2303
2334
|
documentPermissionField,
|
|
2304
|
-
|
|
2335
|
+
requireOperationAccessForPopulateDependencies,
|
|
2336
|
+
requireOperationAccessForPopulateQueries,
|
|
2337
|
+
permissionSchema: targetOptions.permissionSchema,
|
|
2305
2338
|
operationAccess: { read: readOption("operationAccess.read") },
|
|
2306
2339
|
baseFilter: { read: readOption("baseFilter.read") },
|
|
2307
2340
|
overrideFilter: { read: readOption("overrideFilter.read") },
|
|
@@ -2350,13 +2383,13 @@ function captureVirtualPopulateDependencies(runtime, modelName, options, globalO
|
|
|
2350
2383
|
);
|
|
2351
2384
|
continue;
|
|
2352
2385
|
}
|
|
2353
|
-
if (!(0,
|
|
2386
|
+
if (!(0, import_utils16.isPlainObject)(raw)) continue;
|
|
2354
2387
|
const entry = raw;
|
|
2355
2388
|
const label = join(sourcePrefix, name);
|
|
2356
2389
|
captureList(entry.dependsOnPopulate, label);
|
|
2357
2390
|
if (!("get" in entry))
|
|
2358
2391
|
for (const access of accesses) {
|
|
2359
|
-
if ((0,
|
|
2392
|
+
if ((0, import_utils16.isPlainObject)(entry[access]))
|
|
2360
2393
|
captureList(entry[access].dependsOnPopulate, `${label}.${access}`);
|
|
2361
2394
|
}
|
|
2362
2395
|
const byAccess = {};
|
|
@@ -2406,15 +2439,16 @@ function resolveVirtualPopulateDependencies(configuration, scopePath, virtualNam
|
|
|
2406
2439
|
)
|
|
2407
2440
|
);
|
|
2408
2441
|
}
|
|
2409
|
-
var
|
|
2442
|
+
var import_utils16, elementType, join, within, accesses, fail, varyingSchema, varyingModel, snapshots;
|
|
2410
2443
|
var init_virtual_populate_dependencies = __esm({
|
|
2411
2444
|
"src/acl/virtual-populate-dependencies.ts"() {
|
|
2412
|
-
|
|
2445
|
+
import_utils16 = require("@web-ts-toolkit/utils");
|
|
2413
2446
|
init_query();
|
|
2414
2447
|
init_manager();
|
|
2415
2448
|
init_authorization_snapshot();
|
|
2416
2449
|
init_field_catalog();
|
|
2417
2450
|
init_virtual_descriptor();
|
|
2451
|
+
init_populate_target_configuration();
|
|
2418
2452
|
elementType = (type) => type.$embeddedSchemaType ?? type.embeddedSchemaType ?? type.caster;
|
|
2419
2453
|
join = (prefix, path) => prefix ? `${prefix}.${path}` : path;
|
|
2420
2454
|
within = (path, parent) => path === parent || path.startsWith(`${parent}.`);
|
|
@@ -2429,14 +2463,14 @@ var init_virtual_populate_dependencies = __esm({
|
|
|
2429
2463
|
});
|
|
2430
2464
|
|
|
2431
2465
|
// src/runtime.ts
|
|
2432
|
-
var import_mongoose4, import_mongoose_schema_jsonschema,
|
|
2466
|
+
var import_mongoose4, import_mongoose_schema_jsonschema, import_utils17, mongooseJsonSchemaInitialized, ensureMongooseJsonSchemaInitialized, pluralize, FIELD_ACCESS_KEYS, defaultModelOptions, defaultDataOptions, normalizeBasePath, hasModelPermission, classifyPermissionSchema, refreshPermissionMetadata, VIRTUAL_SUPPORTED_ACCESSES, VIRTUAL_UNSUPPORTED_ACCESSES, VIRTUAL_RESERVED_NAMES, VIRTUAL_DANGEROUS_SEGMENTS, VIRTUAL_NAME_PATTERN, isVirtualContainerValue2, virtualFullPath, virtualPathsOverlap, collectStoredTopLevel, getChildSchemaForField, getNestedChildFields, cloneVirtualsForValidation, validateVirtualDependsOn, validateVirtualLeafValue, validateVirtualsScope, validateVirtualsTree, AccessRuntime, defaultRuntime;
|
|
2433
2467
|
var init_runtime = __esm({
|
|
2434
2468
|
"src/runtime.ts"() {
|
|
2435
2469
|
import_mongoose4 = __toESM(require("mongoose"));
|
|
2436
2470
|
init_public_admission();
|
|
2437
2471
|
init_hydration();
|
|
2438
2472
|
import_mongoose_schema_jsonschema = __toESM(require("mongoose-schema-jsonschema"));
|
|
2439
|
-
|
|
2473
|
+
import_utils17 = require("@web-ts-toolkit/utils");
|
|
2440
2474
|
init_helpers();
|
|
2441
2475
|
init_registry();
|
|
2442
2476
|
init_logger_default();
|
|
@@ -2465,44 +2499,44 @@ var init_runtime = __esm({
|
|
|
2465
2499
|
listHardLimit: DEFAULT_LIST_HARD_LIMIT
|
|
2466
2500
|
};
|
|
2467
2501
|
normalizeBasePath = (name, value) => {
|
|
2468
|
-
if ((0,
|
|
2502
|
+
if ((0, import_utils17.isNil)(value)) {
|
|
2469
2503
|
return `/${pluralize(name)}`;
|
|
2470
2504
|
}
|
|
2471
|
-
return (0,
|
|
2505
|
+
return (0, import_utils17.isString)(value) ? (0, import_utils17.addLeadingSlash)(value) : "";
|
|
2472
2506
|
};
|
|
2473
2507
|
hasModelPermission = (value, modelPermissionPrefix) => {
|
|
2474
2508
|
if (!modelPermissionPrefix) {
|
|
2475
2509
|
return true;
|
|
2476
2510
|
}
|
|
2477
|
-
if ((0,
|
|
2511
|
+
if ((0, import_utils17.isString)(value)) {
|
|
2478
2512
|
return value.trim().split(" ").some((item) => item.startsWith(modelPermissionPrefix));
|
|
2479
2513
|
}
|
|
2480
|
-
if ((0,
|
|
2514
|
+
if ((0, import_utils17.isArray)(value)) {
|
|
2481
2515
|
return value.some((item) => {
|
|
2482
|
-
if ((0,
|
|
2516
|
+
if ((0, import_utils17.isString)(item) || (0, import_utils17.isArray)(item)) {
|
|
2483
2517
|
return hasModelPermission(item, modelPermissionPrefix);
|
|
2484
2518
|
}
|
|
2485
2519
|
return true;
|
|
2486
2520
|
});
|
|
2487
2521
|
}
|
|
2488
|
-
return (0,
|
|
2522
|
+
return (0, import_utils17.isFunction)(value);
|
|
2489
2523
|
};
|
|
2490
2524
|
classifyPermissionSchema = (permissionSchema, modelPermissionPrefix) => {
|
|
2491
2525
|
const schemaKeys = Object.keys(permissionSchema);
|
|
2492
2526
|
const globalPermissionKeys = {};
|
|
2493
2527
|
const modelPermissionKeys = {};
|
|
2494
|
-
(0,
|
|
2528
|
+
(0, import_utils17.forEach)(schemaKeys, (schemaKey) => {
|
|
2495
2529
|
const schemaRule = permissionSchema[schemaKey];
|
|
2496
|
-
const ruleEntries = (0,
|
|
2530
|
+
const ruleEntries = (0, import_utils17.isPlainObject)(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
|
|
2497
2531
|
for (let x = 0; x < ruleEntries.length; x++) {
|
|
2498
2532
|
const [accessKey, value] = ruleEntries[x];
|
|
2499
|
-
if (!(0,
|
|
2533
|
+
if (!(0, import_utils17.isArray)(globalPermissionKeys[accessKey])) {
|
|
2500
2534
|
globalPermissionKeys[accessKey] = [];
|
|
2501
2535
|
}
|
|
2502
|
-
if (!(0,
|
|
2536
|
+
if (!(0, import_utils17.isArray)(modelPermissionKeys[accessKey])) {
|
|
2503
2537
|
modelPermissionKeys[accessKey] = [];
|
|
2504
2538
|
}
|
|
2505
|
-
if ((0,
|
|
2539
|
+
if ((0, import_utils17.isBoolean)(value)) {
|
|
2506
2540
|
globalPermissionKeys[accessKey].push(schemaKey);
|
|
2507
2541
|
continue;
|
|
2508
2542
|
}
|
|
@@ -2534,13 +2568,13 @@ var init_runtime = __esm({
|
|
|
2534
2568
|
VIRTUAL_RESERVED_NAMES = /* @__PURE__ */ new Set(["_id", "__v", "id"]);
|
|
2535
2569
|
VIRTUAL_DANGEROUS_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
2536
2570
|
VIRTUAL_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
2537
|
-
isVirtualContainerValue2 = (value) => (0,
|
|
2571
|
+
isVirtualContainerValue2 = (value) => (0, import_utils17.isPlainObject)(value) && "sub" in value;
|
|
2538
2572
|
virtualFullPath = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
2539
2573
|
virtualPathsOverlap = (virtualPath, permissionField) => {
|
|
2540
2574
|
if (!virtualPath || !permissionField) return false;
|
|
2541
2575
|
try {
|
|
2542
|
-
if ((0,
|
|
2543
|
-
if ((0,
|
|
2576
|
+
if ((0, import_utils17.get)((0, import_utils17.set)({}, virtualPath, true), permissionField) !== void 0) return true;
|
|
2577
|
+
if ((0, import_utils17.get)((0, import_utils17.set)({}, permissionField, true), virtualPath) !== void 0) return true;
|
|
2544
2578
|
} catch {
|
|
2545
2579
|
return false;
|
|
2546
2580
|
}
|
|
@@ -2601,12 +2635,12 @@ var init_runtime = __esm({
|
|
|
2601
2635
|
};
|
|
2602
2636
|
validateVirtualDependsOn = (dependsOn, entryLabel, storedFields, siblingVirtualNames) => {
|
|
2603
2637
|
if (dependsOn === void 0) return [];
|
|
2604
|
-
if (!(0,
|
|
2638
|
+
if (!(0, import_utils17.isArray)(dependsOn)) {
|
|
2605
2639
|
throw new Error(`Virtual ${entryLabel}: dependsOn must be an array of top-level persisted field names`);
|
|
2606
2640
|
}
|
|
2607
2641
|
const list = dependsOn;
|
|
2608
2642
|
for (const dep of list) {
|
|
2609
|
-
if (!(0,
|
|
2643
|
+
if (!(0, import_utils17.isString)(dep) || dep.length === 0) {
|
|
2610
2644
|
throw new Error(`Virtual ${entryLabel}: dependsOn entries must be non-empty strings`);
|
|
2611
2645
|
}
|
|
2612
2646
|
if (dep.includes(".")) {
|
|
@@ -2628,12 +2662,12 @@ var init_runtime = __esm({
|
|
|
2628
2662
|
return list;
|
|
2629
2663
|
};
|
|
2630
2664
|
validateVirtualLeafValue = (value, entryLabel, storedFields, siblingVirtualNames, sharedDependsOn) => {
|
|
2631
|
-
if ((0,
|
|
2632
|
-
if (!(0,
|
|
2665
|
+
if ((0, import_utils17.isFunction)(value)) return;
|
|
2666
|
+
if (!(0, import_utils17.isPlainObject)(value)) {
|
|
2633
2667
|
throw new Error(`Virtual ${entryLabel}: descriptor must be a getter function or { get, dependsOn }`);
|
|
2634
2668
|
}
|
|
2635
2669
|
const record3 = value;
|
|
2636
|
-
if (!(0,
|
|
2670
|
+
if (!(0, import_utils17.isFunction)(record3.get)) {
|
|
2637
2671
|
throw new Error(`Virtual ${entryLabel}: descriptor.get must be a callable getter function`);
|
|
2638
2672
|
}
|
|
2639
2673
|
validateVirtualDependsOn(record3.dependsOn ?? sharedDependsOn, entryLabel, storedFields, siblingVirtualNames);
|
|
@@ -2675,7 +2709,7 @@ var init_runtime = __esm({
|
|
|
2675
2709
|
`Virtual ${scopeLabel}${name}: scope-container must only hold "sub" (embedded container "${name}" is not a virtual-leaf collision)`
|
|
2676
2710
|
);
|
|
2677
2711
|
}
|
|
2678
|
-
if (!(0,
|
|
2712
|
+
if (!(0, import_utils17.isPlainObject)(record4.sub)) {
|
|
2679
2713
|
throw new Error(`Virtual ${scopeLabel}${name}: scope-container "sub" must be a plain object`);
|
|
2680
2714
|
}
|
|
2681
2715
|
continue;
|
|
@@ -2685,8 +2719,8 @@ var init_runtime = __esm({
|
|
|
2685
2719
|
`Virtual ${scopeLabel}${name}: collides with a stored path (inspected actual Mongoose schema/child scope; getModelAtt alone is insufficient)`
|
|
2686
2720
|
);
|
|
2687
2721
|
}
|
|
2688
|
-
if ((0,
|
|
2689
|
-
if (!(0,
|
|
2722
|
+
if ((0, import_utils17.isFunction)(raw)) continue;
|
|
2723
|
+
if (!(0, import_utils17.isPlainObject)(raw)) {
|
|
2690
2724
|
throw new Error(
|
|
2691
2725
|
`Virtual ${scopeLabel}${name}: malformed descriptor (expected getter, { get, dependsOn }, or per-access record)`
|
|
2692
2726
|
);
|
|
@@ -2740,7 +2774,7 @@ var init_runtime = __esm({
|
|
|
2740
2774
|
};
|
|
2741
2775
|
validateVirtualsTree = (model, virtuals, documentPermissionField, modelName) => {
|
|
2742
2776
|
if (virtuals === void 0 || virtuals === null) return;
|
|
2743
|
-
if (!(0,
|
|
2777
|
+
if (!(0, import_utils17.isPlainObject)(virtuals)) {
|
|
2744
2778
|
throw new Error(`Virtuals for model "${modelName}": virtuals must be a plain object mapping names to descriptors`);
|
|
2745
2779
|
}
|
|
2746
2780
|
const rootSchema = model?.schema ?? null;
|
|
@@ -2792,8 +2826,8 @@ var init_runtime = __esm({
|
|
|
2792
2826
|
{
|
|
2793
2827
|
requestPermissionField: "_permissions",
|
|
2794
2828
|
globalPermissions: () => ({}),
|
|
2795
|
-
|
|
2796
|
-
|
|
2829
|
+
requireOperationAccessForPopulateQueries: true,
|
|
2830
|
+
requireOperationAccessForPopulateDependencies: true,
|
|
2797
2831
|
logger: defaultLogger,
|
|
2798
2832
|
requestComplexity: defaultRequestComplexity
|
|
2799
2833
|
},
|
|
@@ -2848,7 +2882,7 @@ var init_runtime = __esm({
|
|
|
2848
2882
|
}
|
|
2849
2883
|
registerOpenApiRoute(route) {
|
|
2850
2884
|
this.openApiRegistry.register(
|
|
2851
|
-
this.openApiPathPrefix ? { ...route, path: (0,
|
|
2885
|
+
this.openApiPathPrefix ? { ...route, path: (0, import_utils17.normalizeUrlPath)(`${this.openApiPathPrefix}/${route.path}`) } : route
|
|
2852
2886
|
);
|
|
2853
2887
|
}
|
|
2854
2888
|
/**
|
|
@@ -2859,7 +2893,7 @@ var init_runtime = __esm({
|
|
|
2859
2893
|
*/
|
|
2860
2894
|
withOpenApiPathPrefix(prefix, build) {
|
|
2861
2895
|
const previous = this.openApiPathPrefix;
|
|
2862
|
-
this.openApiPathPrefix = (0,
|
|
2896
|
+
this.openApiPathPrefix = (0, import_utils17.normalizeUrlPath)(`${previous}/${prefix}`);
|
|
2863
2897
|
try {
|
|
2864
2898
|
return build();
|
|
2865
2899
|
} finally {
|
|
@@ -2967,13 +3001,15 @@ var init_runtime = __esm({
|
|
|
2967
3001
|
/** Shallowly replace supplied global values; nested objects such as requestComplexity are not deep-merged. */
|
|
2968
3002
|
setGlobalOptions(options) {
|
|
2969
3003
|
const next = { ...options };
|
|
2970
|
-
if ("
|
|
2971
|
-
next.
|
|
3004
|
+
if ("requireOperationAccessForPopulateQueries" in next)
|
|
3005
|
+
next.requireOperationAccessForPopulateQueries = next.requireOperationAccessForPopulateQueries !== false;
|
|
3006
|
+
if ("requireOperationAccessForPopulateDependencies" in next)
|
|
3007
|
+
next.requireOperationAccessForPopulateDependencies = next.requireOperationAccessForPopulateDependencies !== false;
|
|
2972
3008
|
this.globalOptions.assign(next);
|
|
2973
3009
|
}
|
|
2974
3010
|
setGlobalOption(key, value) {
|
|
2975
|
-
if (key === "
|
|
2976
|
-
this.globalOptions.set(
|
|
3011
|
+
if (key === "requireOperationAccessForPopulateQueries" || key === "requireOperationAccessForPopulateDependencies") {
|
|
3012
|
+
this.globalOptions.set(key, value !== false);
|
|
2977
3013
|
return;
|
|
2978
3014
|
}
|
|
2979
3015
|
this.globalOptions.set(key, value);
|
|
@@ -3002,7 +3038,7 @@ var init_runtime = __esm({
|
|
|
3002
3038
|
if (keyStr === "defaults") assertPublicDefaults(value);
|
|
3003
3039
|
else if (keyStr.startsWith("defaults.")) {
|
|
3004
3040
|
const proposed = {};
|
|
3005
|
-
(0,
|
|
3041
|
+
(0, import_utils17.set)(proposed, keyStr.slice("defaults.".length), value);
|
|
3006
3042
|
assertPublicDefaults(proposed);
|
|
3007
3043
|
}
|
|
3008
3044
|
this.defaultModelOptions.set(key, value);
|
|
@@ -3031,7 +3067,7 @@ var init_runtime = __esm({
|
|
|
3031
3067
|
}).onchange("basePath", function(newval, key, target) {
|
|
3032
3068
|
target[key] = normalizeBasePath(
|
|
3033
3069
|
modelName,
|
|
3034
|
-
(0,
|
|
3070
|
+
(0, import_utils17.isString)(newval) || (0, import_utils17.isNil)(newval) ? newval : void 0
|
|
3035
3071
|
);
|
|
3036
3072
|
}).build();
|
|
3037
3073
|
this.modelJsonSchemas[modelName] = model.jsonSchema();
|
|
@@ -3075,7 +3111,7 @@ var init_runtime = __esm({
|
|
|
3075
3111
|
if (keyStr === "defaults") assertPublicDefaults(value);
|
|
3076
3112
|
else if (keyStr.startsWith("defaults.")) {
|
|
3077
3113
|
const proposed = {};
|
|
3078
|
-
(0,
|
|
3114
|
+
(0, import_utils17.set)(proposed, keyStr.slice("defaults.".length), value);
|
|
3079
3115
|
assertPublicDefaults(proposed);
|
|
3080
3116
|
}
|
|
3081
3117
|
const manager = this.modelOptions[modelName];
|
|
@@ -3096,15 +3132,15 @@ var init_runtime = __esm({
|
|
|
3096
3132
|
const segments = nestedPath.split(".");
|
|
3097
3133
|
let cursor = cloned;
|
|
3098
3134
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
3099
|
-
if (!(0,
|
|
3135
|
+
if (!(0, import_utils17.isPlainObject)(cursor)) break;
|
|
3100
3136
|
cursor = cursor[segments[i]];
|
|
3101
3137
|
}
|
|
3102
|
-
if ((0,
|
|
3138
|
+
if ((0, import_utils17.isPlainObject)(cursor)) {
|
|
3103
3139
|
delete cursor[segments[segments.length - 1]];
|
|
3104
3140
|
}
|
|
3105
3141
|
proposedVirtuals = cloned;
|
|
3106
3142
|
} else {
|
|
3107
|
-
(0,
|
|
3143
|
+
(0, import_utils17.set)(cloned, nestedPath, value);
|
|
3108
3144
|
proposedVirtuals = cloned;
|
|
3109
3145
|
}
|
|
3110
3146
|
}
|
|
@@ -3205,7 +3241,7 @@ var init_runtime = __esm({
|
|
|
3205
3241
|
manager.onchange("basePath", function(newval, key, target) {
|
|
3206
3242
|
target[key] = normalizeBasePath(
|
|
3207
3243
|
dataName,
|
|
3208
|
-
(0,
|
|
3244
|
+
(0, import_utils17.isString)(newval) || (0, import_utils17.isNil)(newval) ? newval : void 0
|
|
3209
3245
|
);
|
|
3210
3246
|
}).build();
|
|
3211
3247
|
return manager;
|
|
@@ -3265,20 +3301,20 @@ var init_runtime = __esm({
|
|
|
3265
3301
|
const schema = model.schema;
|
|
3266
3302
|
this.modelRefs[modelName] = buildRefs(schema.tree);
|
|
3267
3303
|
this.modelSubs[modelName] = buildSubPaths(schema.tree);
|
|
3268
|
-
this.modelAtts[modelName] = (0,
|
|
3304
|
+
this.modelAtts[modelName] = (0, import_utils17.keys)(schema.obj);
|
|
3269
3305
|
}
|
|
3270
3306
|
getModelRef(modelName, refPath) {
|
|
3271
3307
|
this.ensureModelMeta(modelName);
|
|
3272
|
-
const value = (0,
|
|
3273
|
-
return (0,
|
|
3308
|
+
const value = (0, import_utils17.get)(this.modelRefs, `${modelName}.${refPath}`, null);
|
|
3309
|
+
return (0, import_utils17.isString)(value) ? value : null;
|
|
3274
3310
|
}
|
|
3275
3311
|
getModelSub(modelName) {
|
|
3276
3312
|
this.ensureModelMeta(modelName);
|
|
3277
|
-
return (0,
|
|
3313
|
+
return (0, import_utils17.get)(this.modelSubs, modelName, []);
|
|
3278
3314
|
}
|
|
3279
3315
|
getModelAtt(modelName) {
|
|
3280
3316
|
this.ensureModelMeta(modelName);
|
|
3281
|
-
return (0,
|
|
3317
|
+
return (0, import_utils17.get)(this.modelAtts, modelName, []);
|
|
3282
3318
|
}
|
|
3283
3319
|
};
|
|
3284
3320
|
defaultRuntime = new AccessRuntime({ allowGlobalModelLookup: true });
|
|
@@ -3454,10 +3490,10 @@ var init_options = __esm({
|
|
|
3454
3490
|
});
|
|
3455
3491
|
|
|
3456
3492
|
// src/permission.ts
|
|
3457
|
-
var
|
|
3493
|
+
var import_utils18, Permission, permission_default;
|
|
3458
3494
|
var init_permission = __esm({
|
|
3459
3495
|
"src/permission.ts"() {
|
|
3460
|
-
|
|
3496
|
+
import_utils18 = require("@web-ts-toolkit/utils");
|
|
3461
3497
|
Permission = class {
|
|
3462
3498
|
constructor(permissions) {
|
|
3463
3499
|
this.permissions = { ...permissions };
|
|
@@ -3473,7 +3509,7 @@ var init_permission = __esm({
|
|
|
3473
3509
|
return [permissionOrPermissions].concat(permissions);
|
|
3474
3510
|
}
|
|
3475
3511
|
hasKey(permission) {
|
|
3476
|
-
return (0,
|
|
3512
|
+
return (0, import_utils18.hasOwn)(this.permissions, permission);
|
|
3477
3513
|
}
|
|
3478
3514
|
has(permission) {
|
|
3479
3515
|
return this.permissions[permission] === true;
|
|
@@ -3507,6 +3543,47 @@ function serviceAuthorizationInput(policy, targets) {
|
|
|
3507
3543
|
}
|
|
3508
3544
|
return { rows: policy.rows, outputFields: policy.outputFields, related };
|
|
3509
3545
|
}
|
|
3546
|
+
function hasStableConfigurationCopies(value) {
|
|
3547
|
+
if (value === null || typeof value !== "object") return true;
|
|
3548
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype) return false;
|
|
3549
|
+
return Object.values(value).every(hasStableConfigurationCopies);
|
|
3550
|
+
}
|
|
3551
|
+
function captureAuthorizationAccess(value) {
|
|
3552
|
+
const input = authorizationRecord(value, "access");
|
|
3553
|
+
const access = {};
|
|
3554
|
+
for (const key of ["operation", "rowAccess", "virtualAccess", "outputAccess", "docPermissionsAccess"]) {
|
|
3555
|
+
if (key === "rowAccess" && input[key] === void 0) continue;
|
|
3556
|
+
if (typeof input[key] !== "string") authorizationError(`invalid access.${key}`);
|
|
3557
|
+
access[key] = input[key];
|
|
3558
|
+
}
|
|
3559
|
+
return Object.freeze(access);
|
|
3560
|
+
}
|
|
3561
|
+
function captureAuthorizationCatalog(value) {
|
|
3562
|
+
const input = authorizationRecord(value, "catalog");
|
|
3563
|
+
const catalog = {};
|
|
3564
|
+
for (const key of [
|
|
3565
|
+
"paths",
|
|
3566
|
+
"persistedPaths",
|
|
3567
|
+
"arrayPaths",
|
|
3568
|
+
"schemaVirtualPaths",
|
|
3569
|
+
"metadataPaths",
|
|
3570
|
+
"dynamicPaths",
|
|
3571
|
+
"containerPaths",
|
|
3572
|
+
"virtualPaths",
|
|
3573
|
+
"virtualScopePaths",
|
|
3574
|
+
"opaquePaths",
|
|
3575
|
+
"referencePaths",
|
|
3576
|
+
"protectedPaths"
|
|
3577
|
+
]) {
|
|
3578
|
+
const paths = input[key];
|
|
3579
|
+
if (key !== "paths" && paths === void 0) continue;
|
|
3580
|
+
if (!Array.isArray(paths) || Array.from(paths).some((path) => typeof path !== "string")) {
|
|
3581
|
+
authorizationError(`invalid catalog.${key}`);
|
|
3582
|
+
}
|
|
3583
|
+
catalog[key] = paths;
|
|
3584
|
+
}
|
|
3585
|
+
return Object.freeze(catalog);
|
|
3586
|
+
}
|
|
3510
3587
|
function assertAuthorizationPath(path) {
|
|
3511
3588
|
if (typeof path !== "string" || !isSafeOutputPath(path)) {
|
|
3512
3589
|
authorizationError(`invalid response path: ${String(path)}`);
|
|
@@ -3591,7 +3668,6 @@ function normalizePolicy(value, applicability, configuration, targets) {
|
|
|
3591
3668
|
const matches = targets.filter((target2) => target2.path === path);
|
|
3592
3669
|
if (matches.length !== 1) authorizationError(`unused or ambiguous related path: ${path}`);
|
|
3593
3670
|
const target = matches[0];
|
|
3594
|
-
if (target.kind === "passthrough") authorizationError(`related policy requires a registered target: ${path}`);
|
|
3595
3671
|
const child = authorizationRecord(entry, `related.${path}`);
|
|
3596
3672
|
assertAuthorizationKeys(
|
|
3597
3673
|
child,
|
|
@@ -3637,6 +3713,9 @@ function resolveServiceAuthorization(input) {
|
|
|
3637
3713
|
const raw = copyAuthorizationValue(input.authorization);
|
|
3638
3714
|
const configuration = copyAuthorizationValue(input.configuration, true);
|
|
3639
3715
|
const targets = copyAuthorizationValue(input.relatedTargets ?? [], true);
|
|
3716
|
+
const access = copyAuthorizationValue(input.access);
|
|
3717
|
+
const outputAccess = captureAuthorizationAccess(access);
|
|
3718
|
+
const catalog = captureAuthorizationCatalog(configuration.catalog);
|
|
3640
3719
|
const policy = copyAuthorizationValue(normalizePolicy(raw, input.applicability ?? "service", configuration, targets));
|
|
3641
3720
|
const scopePath = Array.from(scope(input.binding));
|
|
3642
3721
|
for (const part of scopePath) {
|
|
@@ -3649,17 +3728,21 @@ function resolveServiceAuthorization(input) {
|
|
|
3649
3728
|
authorizationError("derived call request/runtime mismatch");
|
|
3650
3729
|
}
|
|
3651
3730
|
}
|
|
3652
|
-
const permissions =
|
|
3653
|
-
input.requestPermissions.keys.map((key) => [key, input.requestPermissions.has(key)])
|
|
3731
|
+
const permissions = new permission_default(
|
|
3732
|
+
Object.fromEntries(input.requestPermissions.keys.map((key) => [key, input.requestPermissions.has(key) === true]))
|
|
3654
3733
|
);
|
|
3734
|
+
for (const value of Object.values(permissions)) if (value && typeof value === "object") Object.freeze(value);
|
|
3735
|
+
Object.freeze(permissions);
|
|
3655
3736
|
const call = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
3656
3737
|
calls.set(call, {
|
|
3657
3738
|
binding: Object.freeze({ ...input.binding, scopePath: Object.freeze(scopePath) }),
|
|
3658
|
-
access
|
|
3739
|
+
access,
|
|
3659
3740
|
configuration,
|
|
3660
3741
|
policy,
|
|
3661
3742
|
relatedTargets: targets,
|
|
3662
|
-
|
|
3743
|
+
// normalizeFields constructs only mode strings and validated string paths.
|
|
3744
|
+
output: Object.freeze({ access: outputAccess, catalog, outputFields: policy.outputFields }),
|
|
3745
|
+
permissions,
|
|
3663
3746
|
provenance: input.parent ? callRecord(input.parent).provenance : call
|
|
3664
3747
|
});
|
|
3665
3748
|
return call;
|
|
@@ -3677,12 +3760,75 @@ function readServiceAuthorization(call, binding) {
|
|
|
3677
3760
|
true
|
|
3678
3761
|
);
|
|
3679
3762
|
}
|
|
3763
|
+
function readServiceAuthorizationAccess(call, binding) {
|
|
3764
|
+
assertAuthorizationBinding(call, binding);
|
|
3765
|
+
return callRecord(call).output.access;
|
|
3766
|
+
}
|
|
3767
|
+
function readServiceAuthorizationHydration(call, binding) {
|
|
3768
|
+
assertAuthorizationBinding(call, binding);
|
|
3769
|
+
return copyAuthorizationValue({ hydration: callRecord(call).configuration.hydration }, true);
|
|
3770
|
+
}
|
|
3771
|
+
function outputMetadata(configuration) {
|
|
3772
|
+
return {
|
|
3773
|
+
documentPermissionField: configuration.documentPermissionField,
|
|
3774
|
+
exposedDocPermissionKeys: configuration.exposedDocPermissionKeys,
|
|
3775
|
+
stripPermissionsField: configuration.stripPermissionsField,
|
|
3776
|
+
disableFieldPermissions: configuration.disableFieldPermissions
|
|
3777
|
+
};
|
|
3778
|
+
}
|
|
3779
|
+
function readServiceOutputMetadata(call, binding) {
|
|
3780
|
+
assertAuthorizationBinding(call, binding);
|
|
3781
|
+
return copyAuthorizationValue(outputMetadata(callRecord(call).configuration), true);
|
|
3782
|
+
}
|
|
3783
|
+
function readServiceDocumentPermissions(call, binding) {
|
|
3784
|
+
assertAuthorizationBinding(call, binding);
|
|
3785
|
+
const record3 = callRecord(call);
|
|
3786
|
+
return Object.freeze({
|
|
3787
|
+
catalog: record3.output.catalog,
|
|
3788
|
+
...copyAuthorizationValue({ docPermissions: record3.configuration.docPermissions }, true)
|
|
3789
|
+
});
|
|
3790
|
+
}
|
|
3791
|
+
function readServiceFinalizerConfiguration(call, binding) {
|
|
3792
|
+
assertAuthorizationBinding(call, binding);
|
|
3793
|
+
const record3 = callRecord(call);
|
|
3794
|
+
return Object.freeze({
|
|
3795
|
+
catalog: record3.output.catalog,
|
|
3796
|
+
...copyAuthorizationValue(
|
|
3797
|
+
{
|
|
3798
|
+
...outputMetadata(record3.configuration),
|
|
3799
|
+
virtuals: record3.configuration.virtuals,
|
|
3800
|
+
docPermissions: record3.configuration.docPermissions
|
|
3801
|
+
},
|
|
3802
|
+
true
|
|
3803
|
+
)
|
|
3804
|
+
});
|
|
3805
|
+
}
|
|
3806
|
+
function readServiceOutputPolicy(call, binding) {
|
|
3807
|
+
assertAuthorizationBinding(call, binding);
|
|
3808
|
+
return callRecord(call).output;
|
|
3809
|
+
}
|
|
3810
|
+
function readServiceOutputFieldAuthorization(call, binding) {
|
|
3811
|
+
assertAuthorizationBinding(call, binding);
|
|
3812
|
+
const record3 = callRecord(call);
|
|
3813
|
+
const reusable = record3.reusableFieldConfiguration ??= hasStableConfigurationCopies(record3.configuration.permissionSchema) && // Coercion methods can observe an object's identity even without native
|
|
3814
|
+
// leaves. Keep those receivers local to the original resolution boundary.
|
|
3815
|
+
(record3.configuration.modelPermissionPrefix === null || typeof record3.configuration.modelPermissionPrefix !== "object");
|
|
3816
|
+
return Object.freeze({
|
|
3817
|
+
access: record3.output.access,
|
|
3818
|
+
outputFields: record3.output.outputFields,
|
|
3819
|
+
reusable,
|
|
3820
|
+
...copyAuthorizationValue(
|
|
3821
|
+
{
|
|
3822
|
+
permissionSchema: record3.configuration.permissionSchema,
|
|
3823
|
+
modelPermissionPrefix: record3.configuration.modelPermissionPrefix
|
|
3824
|
+
},
|
|
3825
|
+
true
|
|
3826
|
+
)
|
|
3827
|
+
});
|
|
3828
|
+
}
|
|
3680
3829
|
function getAuthorizationPermissions(call, binding) {
|
|
3681
3830
|
assertAuthorizationBinding(call, binding);
|
|
3682
|
-
|
|
3683
|
-
for (const value of Object.values(permission)) if (value && typeof value === "object") Object.freeze(value);
|
|
3684
|
-
Object.freeze(permission);
|
|
3685
|
-
return permission;
|
|
3831
|
+
return callRecord(call).permissions;
|
|
3686
3832
|
}
|
|
3687
3833
|
function getAuthorizationProvenance(call) {
|
|
3688
3834
|
return callRecord(call).provenance;
|
|
@@ -3721,7 +3867,7 @@ function normalizeOutputAuthorizationOptions(input, options, purpose) {
|
|
|
3721
3867
|
const stage = stageRecord(documentRecord(handle).stage);
|
|
3722
3868
|
const binding = Object.freeze({ ...input.binding, scopePath: stage.binding.scopePath });
|
|
3723
3869
|
assertAuthorizationBinding(stage.call, binding);
|
|
3724
|
-
const access =
|
|
3870
|
+
const access = readServiceAuthorizationAccess(stage.call, binding);
|
|
3725
3871
|
if (input.access.outputAccess !== access.outputAccess) authorizationError("document access mismatch");
|
|
3726
3872
|
return Object.freeze({ kind: "document", documentAuthorization: handle, binding });
|
|
3727
3873
|
}
|
|
@@ -3799,7 +3945,16 @@ function readDocumentAuthorization(handle, binding) {
|
|
|
3799
3945
|
authorization: stage.call,
|
|
3800
3946
|
stage: record3.stage,
|
|
3801
3947
|
grants: copyAuthorizationValue(record3.grants),
|
|
3802
|
-
...
|
|
3948
|
+
...readServiceAuthorizationAccess(stage.call, binding)
|
|
3949
|
+
});
|
|
3950
|
+
}
|
|
3951
|
+
function readDocumentAuthorizationAccess(handle, binding) {
|
|
3952
|
+
const record3 = documentRecord(handle);
|
|
3953
|
+
const stage = stageRecord(record3.stage);
|
|
3954
|
+
return Object.freeze({
|
|
3955
|
+
authorization: stage.call,
|
|
3956
|
+
stage: record3.stage,
|
|
3957
|
+
...readServiceAuthorizationAccess(stage.call, binding)
|
|
3803
3958
|
});
|
|
3804
3959
|
}
|
|
3805
3960
|
function memoizeDocumentFieldDecision(handle, binding, field, evaluate) {
|
|
@@ -3807,15 +3962,23 @@ function memoizeDocumentFieldDecision(handle, binding, field, evaluate) {
|
|
|
3807
3962
|
const stage = stageRecord(record3.stage);
|
|
3808
3963
|
assertAuthorizationBinding(stage.call, binding);
|
|
3809
3964
|
let decision = record3.decisions.get(field);
|
|
3810
|
-
if (
|
|
3965
|
+
if (decision) {
|
|
3966
|
+
return decision.then((result2) => {
|
|
3967
|
+
stageRecord(record3.stage);
|
|
3968
|
+
assertAuthorizationBinding(stage.call, binding);
|
|
3969
|
+
return result2;
|
|
3970
|
+
});
|
|
3971
|
+
} else {
|
|
3811
3972
|
decision = Promise.resolve().then(async () => {
|
|
3812
3973
|
stageRecord(record3.stage);
|
|
3974
|
+
assertAuthorizationBinding(stage.call, binding);
|
|
3813
3975
|
const result2 = await evaluate.call(
|
|
3814
3976
|
stage.binding.request,
|
|
3815
3977
|
getAuthorizationPermissions(stage.call, binding),
|
|
3816
3978
|
copyAuthorizationValue(record3.grants)
|
|
3817
3979
|
);
|
|
3818
3980
|
stageRecord(record3.stage);
|
|
3981
|
+
assertAuthorizationBinding(stage.call, binding);
|
|
3819
3982
|
if (typeof result2 !== "boolean") authorizationError("field decision must be boolean");
|
|
3820
3983
|
return result2;
|
|
3821
3984
|
});
|
|
@@ -3832,7 +3995,7 @@ function assertDocumentAuthorization(handle, use) {
|
|
|
3832
3995
|
const record3 = documentRecord(handle);
|
|
3833
3996
|
const stage = stageRecord(record3.stage);
|
|
3834
3997
|
assertAuthorizationBinding(stage.call, use.binding);
|
|
3835
|
-
if (use.authorization !== void 0 && stage.call !== use.authorization || use.stage !== void 0 && record3.stage !== use.stage ||
|
|
3998
|
+
if (use.authorization !== void 0 && stage.call !== use.authorization || use.stage !== void 0 && record3.stage !== use.stage || readServiceAuthorizationAccess(stage.call, use.binding).outputAccess !== use.outputAccess) {
|
|
3836
3999
|
authorizationError("document call/access/stage mismatch");
|
|
3837
4000
|
}
|
|
3838
4001
|
const association = outputs.get(use.output);
|
|
@@ -3887,7 +4050,7 @@ function transferDocumentAuthorizationGraph(source, copy, copyOrigins) {
|
|
|
3887
4050
|
{
|
|
3888
4051
|
binding: stage.binding,
|
|
3889
4052
|
output: original,
|
|
3890
|
-
outputAccess:
|
|
4053
|
+
outputAccess: readServiceAuthorizationAccess(stage.call, stage.binding).outputAccess,
|
|
3891
4054
|
authorization: stage.call,
|
|
3892
4055
|
stage: documentRecord(association.handle).stage
|
|
3893
4056
|
},
|
|
@@ -3960,7 +4123,7 @@ function attachIncludeOutput(doc, path, value) {
|
|
|
3960
4123
|
const state = stateFor(doc);
|
|
3961
4124
|
if (!state) throw new Error("Include attachment requires a prepared output row");
|
|
3962
4125
|
state.attachments.push({ path, value });
|
|
3963
|
-
(0,
|
|
4126
|
+
(0, import_utils19.set)(doc, path, deepIsolateValue(value));
|
|
3964
4127
|
}
|
|
3965
4128
|
function getIncludeSource(doc) {
|
|
3966
4129
|
return stateFor(doc)?.source ?? doc;
|
|
@@ -3975,14 +4138,14 @@ function restoreIncludeOutput(doc, output) {
|
|
|
3975
4138
|
for (const { path, value } of attachments) {
|
|
3976
4139
|
const copy = deepIsolateValue(value);
|
|
3977
4140
|
if (copy !== null && typeof copy === "object") origins.set(copy, value);
|
|
3978
|
-
(0,
|
|
4141
|
+
(0, import_utils19.set)(output, path, copy);
|
|
3979
4142
|
}
|
|
3980
4143
|
return origins;
|
|
3981
4144
|
}
|
|
3982
|
-
var
|
|
4145
|
+
var import_utils19, outputs2, stateFor;
|
|
3983
4146
|
var init_include_output = __esm({
|
|
3984
4147
|
"src/output/include-output.ts"() {
|
|
3985
|
-
|
|
4148
|
+
import_utils19 = require("@web-ts-toolkit/utils");
|
|
3986
4149
|
init_document_authorization();
|
|
3987
4150
|
init_document();
|
|
3988
4151
|
outputs2 = /* @__PURE__ */ new WeakMap();
|
|
@@ -4052,12 +4215,20 @@ function classifyRequestFieldRule(rule, permissions, modelPermissionPrefix = "")
|
|
|
4052
4215
|
);
|
|
4053
4216
|
return (typeof rule === "string" ? possible.stringHandler(rule) : possible.arrayHandler(rule)) ? "deferred" : "denied";
|
|
4054
4217
|
}
|
|
4218
|
+
function prepareRequestFieldRule(rule, permissions, modelPermissionPrefix = "") {
|
|
4219
|
+
const state = classifyRequestFieldRule(rule, permissions, modelPermissionPrefix);
|
|
4220
|
+
const invariant = state === "denied" && modelPermissionPrefix ? classifyRequestFieldRule(rule, permissions) : state;
|
|
4221
|
+
return Object.freeze({ state, decision: invariant === "deferred" ? void 0 : invariant === "granted" });
|
|
4222
|
+
}
|
|
4223
|
+
function combineFieldAuthorizationStates(states2) {
|
|
4224
|
+
return states2.includes("denied") ? "denied" : states2.includes("deferred") ? "deferred" : "granted";
|
|
4225
|
+
}
|
|
4055
4226
|
function classifyEffectiveFieldAuthorization(args) {
|
|
4056
4227
|
if (hasExplicitFieldGrant(args.outputFields, args.path)) return "granted";
|
|
4057
4228
|
const states2 = args.rules.map(
|
|
4058
4229
|
(rule) => classifyRequestFieldRule(rule, args.globalPermissions, args.modelPermissionPrefix)
|
|
4059
4230
|
);
|
|
4060
|
-
return
|
|
4231
|
+
return combineFieldAuthorizationStates(states2);
|
|
4061
4232
|
}
|
|
4062
4233
|
async function evaluateScopedAccessRule(args) {
|
|
4063
4234
|
const { req, rule, globalPermissions, docPermissions, modelPermissionPrefix } = args;
|
|
@@ -4324,10 +4495,10 @@ function planVirtualProjection(args) {
|
|
|
4324
4495
|
relatedPlans
|
|
4325
4496
|
};
|
|
4326
4497
|
}
|
|
4327
|
-
var
|
|
4498
|
+
var import_utils21, getScopedPermissionSchema, resolveAlwaysSelectForAccess, stripVirtualsFromNormalizedSelect, snapshotVirtualPaths, stripLeadingDash, dbPrefixForScope, toDbPath;
|
|
4328
4499
|
var init_virtual_projection = __esm({
|
|
4329
4500
|
"src/acl/virtual-projection.ts"() {
|
|
4330
|
-
|
|
4501
|
+
import_utils21 = require("@web-ts-toolkit/utils");
|
|
4331
4502
|
init_query();
|
|
4332
4503
|
init_field_authorization();
|
|
4333
4504
|
init_output_projection();
|
|
@@ -4335,20 +4506,20 @@ var init_virtual_projection = __esm({
|
|
|
4335
4506
|
init_virtual_populate_dependencies();
|
|
4336
4507
|
init_virtual_descriptor();
|
|
4337
4508
|
getScopedPermissionSchema = (root, scopePath) => {
|
|
4338
|
-
if (!root || !(0,
|
|
4509
|
+
if (!root || !(0, import_utils21.isPlainObject)(root)) return null;
|
|
4339
4510
|
if (scopePath.length === 0) return root;
|
|
4340
|
-
const scoped = (0,
|
|
4341
|
-
return (0,
|
|
4511
|
+
const scoped = (0, import_utils21.get)(root, scopePath.join("."));
|
|
4512
|
+
return (0, import_utils21.isPlainObject)(scoped) ? scoped : null;
|
|
4342
4513
|
};
|
|
4343
4514
|
resolveAlwaysSelectForAccess = (raw, access) => {
|
|
4344
4515
|
if (!raw) return [];
|
|
4345
|
-
if ((0,
|
|
4346
|
-
if ((0,
|
|
4516
|
+
if ((0, import_utils21.isArray)(raw)) return [...raw];
|
|
4517
|
+
if ((0, import_utils21.isPlainObject)(raw)) {
|
|
4347
4518
|
const record3 = raw;
|
|
4348
4519
|
const exact = record3[access];
|
|
4349
|
-
if ((0,
|
|
4520
|
+
if ((0, import_utils21.isArray)(exact)) return [...exact];
|
|
4350
4521
|
const def = record3.default;
|
|
4351
|
-
if ((0,
|
|
4522
|
+
if ((0, import_utils21.isArray)(def)) return [...def];
|
|
4352
4523
|
return [];
|
|
4353
4524
|
}
|
|
4354
4525
|
return [];
|
|
@@ -4613,8 +4784,8 @@ var init_output_projection = __esm({
|
|
|
4613
4784
|
|
|
4614
4785
|
// src/acl/model-output-planning.ts
|
|
4615
4786
|
function getCapturedAuthorizationOption(configuration, key) {
|
|
4616
|
-
const defaultValue = key.startsWith("operationAccess.") ? (0,
|
|
4617
|
-
return resolveNestedOption((path, fallback) => (0,
|
|
4787
|
+
const defaultValue = key.startsWith("operationAccess.") ? (0, import_utils22.get)(configuration.operationAccessDefaults, key.slice("operationAccess.".length)) : void 0;
|
|
4788
|
+
return resolveNestedOption((path, fallback) => (0, import_utils22.get)(configuration, path, fallback), key, defaultValue);
|
|
4618
4789
|
}
|
|
4619
4790
|
function captureModelAuthorizationConfiguration(runtime, modelName, options = runtime.getModelOptions(modelName), globalOptions = runtime.getGlobalOptions()) {
|
|
4620
4791
|
const model = runtime.getModelInstance(modelName);
|
|
@@ -4629,9 +4800,9 @@ function captureModelAuthorizationConfiguration(runtime, modelName, options = ru
|
|
|
4629
4800
|
options,
|
|
4630
4801
|
globalOptions
|
|
4631
4802
|
),
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
permissionSchema: options.permissionSchema,
|
|
4803
|
+
requireOperationAccessForPopulateDependencies: globalOptions.requireOperationAccessForPopulateDependencies !== false,
|
|
4804
|
+
requireOperationAccessForPopulateQueries: globalOptions.requireOperationAccessForPopulateQueries !== false,
|
|
4805
|
+
permissionSchema: options.permissionSchema === void 0 ? runtime.getDefaultModelOption("permissionSchema") : options.permissionSchema,
|
|
4635
4806
|
virtuals,
|
|
4636
4807
|
alwaysSelectFields: options.alwaysSelectFields,
|
|
4637
4808
|
modelPermissionPrefix: options.modelPermissionPrefix,
|
|
@@ -4677,10 +4848,10 @@ function planModelOutputForHelper(args) {
|
|
|
4677
4848
|
requestedSelect: args.select
|
|
4678
4849
|
});
|
|
4679
4850
|
}
|
|
4680
|
-
var
|
|
4851
|
+
var import_utils22;
|
|
4681
4852
|
var init_model_output_planning = __esm({
|
|
4682
4853
|
"src/acl/model-output-planning.ts"() {
|
|
4683
|
-
|
|
4854
|
+
import_utils22 = require("@web-ts-toolkit/utils");
|
|
4684
4855
|
init_manager();
|
|
4685
4856
|
init_field_catalog();
|
|
4686
4857
|
init_authorization_snapshot();
|
|
@@ -4692,10 +4863,10 @@ var init_model_output_planning = __esm({
|
|
|
4692
4863
|
|
|
4693
4864
|
// src/core-shared.ts
|
|
4694
4865
|
function isAndFilter(filter2) {
|
|
4695
|
-
return !!filter2 && (0,
|
|
4866
|
+
return !!filter2 && (0, import_utils23.isPlainObject)(filter2) && Object.keys(filter2).length === 1 && (0, import_utils23.isArray)(filter2.$and);
|
|
4696
4867
|
}
|
|
4697
4868
|
function isMergeableClause(filter2) {
|
|
4698
|
-
return !!filter2 && (0,
|
|
4869
|
+
return !!filter2 && (0, import_utils23.isPlainObject)(filter2) && Object.keys(filter2).every((key) => !key.startsWith("$"));
|
|
4699
4870
|
}
|
|
4700
4871
|
function optimizeAndFilter(clausesInput) {
|
|
4701
4872
|
const clauses = [];
|
|
@@ -4712,11 +4883,11 @@ function optimizeAndFilter(clausesInput) {
|
|
|
4712
4883
|
const dedupeKey = (value) => {
|
|
4713
4884
|
if (value instanceof RegExp) return `regexp:${JSON.stringify([value.source, value.flags])}`;
|
|
4714
4885
|
if (value instanceof Date) return `date:${value.getTime()}`;
|
|
4715
|
-
if ((0,
|
|
4886
|
+
if ((0, import_utils23.isArray)(value)) {
|
|
4716
4887
|
const entries = Array.from(value, dedupeKey);
|
|
4717
4888
|
return entries.every((entry) => entry !== void 0) ? `array:${JSON.stringify(entries)}` : void 0;
|
|
4718
4889
|
}
|
|
4719
|
-
if ((0,
|
|
4890
|
+
if ((0, import_utils23.isPlainObject)(value)) {
|
|
4720
4891
|
const entries = Object.keys(value).sort().map((key) => [key, dedupeKey(value[key])]);
|
|
4721
4892
|
return entries.every(([, entry]) => entry !== void 0) ? `object:${JSON.stringify(entries)}` : void 0;
|
|
4722
4893
|
}
|
|
@@ -4746,7 +4917,7 @@ function optimizeAndFilter(clausesInput) {
|
|
|
4746
4917
|
}
|
|
4747
4918
|
let canMerge = true;
|
|
4748
4919
|
for (const [key, value] of Object.entries(clause)) {
|
|
4749
|
-
if ((0,
|
|
4920
|
+
if ((0, import_utils23.hasOwn)(mergedClause, key) && !(0, import_node_util4.isDeepStrictEqual)(mergedClause[key], value)) {
|
|
4750
4921
|
canMerge = false;
|
|
4751
4922
|
break;
|
|
4752
4923
|
}
|
|
@@ -4757,24 +4928,24 @@ function optimizeAndFilter(clausesInput) {
|
|
|
4757
4928
|
}
|
|
4758
4929
|
Object.assign(mergedClause, clause);
|
|
4759
4930
|
}
|
|
4760
|
-
const finalClauses = (0,
|
|
4931
|
+
const finalClauses = (0, import_utils23.isEmpty)(mergedClause) ? remainingClauses : [mergedClause, ...remainingClauses];
|
|
4761
4932
|
if (finalClauses.length === 0) return null;
|
|
4762
4933
|
if (finalClauses.length === 1) return finalClauses[0];
|
|
4763
4934
|
return { $and: finalClauses };
|
|
4764
4935
|
}
|
|
4765
4936
|
function normalizeFilter(filter2) {
|
|
4766
4937
|
if (filter2 === false) return false;
|
|
4767
|
-
if (!filter2 || !(0,
|
|
4938
|
+
if (!filter2 || !(0, import_utils23.isPlainObject)(filter2) || (0, import_utils23.isEmpty)(filter2)) return null;
|
|
4768
4939
|
if (!isAndFilter(filter2)) {
|
|
4769
4940
|
return filter2;
|
|
4770
4941
|
}
|
|
4771
4942
|
return optimizeAndFilter(filter2.$and);
|
|
4772
4943
|
}
|
|
4773
4944
|
async function resolveIdentifierFilter(req, idField, resolveIdFilter, id) {
|
|
4774
|
-
if ((0,
|
|
4945
|
+
if ((0, import_utils23.isFunction)(resolveIdFilter)) {
|
|
4775
4946
|
return await resolveIdFilter.call(req, id);
|
|
4776
4947
|
}
|
|
4777
|
-
if ((0,
|
|
4948
|
+
if ((0, import_utils23.isString)(idField)) {
|
|
4778
4949
|
return { [idField]: id };
|
|
4779
4950
|
}
|
|
4780
4951
|
return { _id: id };
|
|
@@ -4798,7 +4969,7 @@ async function resolveAccessFilterParts({
|
|
|
4798
4969
|
}
|
|
4799
4970
|
const overrideFilterFn = getOption(`overrideFilter.${access}`, null);
|
|
4800
4971
|
const baseFilterFn = rows2.mode === "request" ? getOption(`baseFilter.${access}`, null) : null;
|
|
4801
|
-
if (nextFilter !== false && (0,
|
|
4972
|
+
if (nextFilter !== false && (0, import_utils23.isFunction)(overrideFilterFn)) {
|
|
4802
4973
|
nextFilter = normalizeFilter(await overrideFilterFn.call(req, nextFilter, permissions));
|
|
4803
4974
|
}
|
|
4804
4975
|
if (nextFilter === false) return { transformed: false, scope: {}, filter: false };
|
|
@@ -4806,7 +4977,7 @@ async function resolveAccessFilterParts({
|
|
|
4806
4977
|
const scope2 = rows2.mode === "scope" ? rows2.filter : {};
|
|
4807
4978
|
return { transformed: nextFilter ?? {}, scope: scope2, filter: intersectFilters(nextFilter, scope2) };
|
|
4808
4979
|
}
|
|
4809
|
-
if (!(0,
|
|
4980
|
+
if (!(0, import_utils23.isFunction)(baseFilterFn)) return { transformed: nextFilter ?? {}, scope: {}, filter: nextFilter ?? {} };
|
|
4810
4981
|
const cached = cache.get(cacheKey);
|
|
4811
4982
|
const reusable = cached?.resolver === baseFilterFn;
|
|
4812
4983
|
const baseFilter = normalizeFilter(
|
|
@@ -4841,34 +5012,34 @@ async function setRequestPermissions(req) {
|
|
|
4841
5012
|
if (owner === activeRuntime) return;
|
|
4842
5013
|
if (hasFieldValue && owner === void 0) return;
|
|
4843
5014
|
const globalPermissions = getGlobalOption("globalPermissions");
|
|
4844
|
-
const permissions = (0,
|
|
4845
|
-
if ((0,
|
|
4846
|
-
else if ((0,
|
|
4847
|
-
else if ((0,
|
|
5015
|
+
const permissions = (0, import_utils23.isFunction)(globalPermissions) ? await globalPermissions.call(req, req) : void 0;
|
|
5016
|
+
if ((0, import_utils23.isPlainObject)(permissions)) req[requestPermissionField] = permissions;
|
|
5017
|
+
else if ((0, import_utils23.isArray)(permissions)) req[requestPermissionField] = (0, import_utils23.arrayToRecord)(permissions);
|
|
5018
|
+
else if ((0, import_utils23.isString)(permissions)) req[requestPermissionField] = { [permissions]: true };
|
|
4848
5019
|
else req[requestPermissionField] = {};
|
|
4849
5020
|
owners.set(requestPermissionField, activeRuntime);
|
|
4850
5021
|
}
|
|
4851
5022
|
async function evaluateRouteGuard(req, permissions, routeGuard) {
|
|
4852
5023
|
const phas = (key) => permissions.has(key);
|
|
4853
5024
|
const { stringHandler, arrayHandler } = createValidator(phas);
|
|
4854
|
-
if ((0,
|
|
5025
|
+
if ((0, import_utils23.isBoolean)(routeGuard)) {
|
|
4855
5026
|
return routeGuard === true;
|
|
4856
5027
|
}
|
|
4857
|
-
if ((0,
|
|
5028
|
+
if ((0, import_utils23.isString)(routeGuard)) {
|
|
4858
5029
|
return stringHandler(routeGuard);
|
|
4859
5030
|
}
|
|
4860
|
-
if ((0,
|
|
5031
|
+
if ((0, import_utils23.isArray)(routeGuard)) {
|
|
4861
5032
|
return arrayHandler(routeGuard);
|
|
4862
5033
|
}
|
|
4863
|
-
if ((0,
|
|
5034
|
+
if ((0, import_utils23.isFunction)(routeGuard)) {
|
|
4864
5035
|
return routeGuard.call(req, permissions);
|
|
4865
5036
|
}
|
|
4866
5037
|
return false;
|
|
4867
5038
|
}
|
|
4868
5039
|
async function callHookChain(req, hook, doc, permissions, context) {
|
|
4869
|
-
const hooks = (0,
|
|
5040
|
+
const hooks = (0, import_utils23.castArray)(hook);
|
|
4870
5041
|
for (let x = 0; x < hooks.length; x++) {
|
|
4871
|
-
if ((0,
|
|
5042
|
+
if ((0, import_utils23.isFunction)(hooks[x])) {
|
|
4872
5043
|
doc = await hooks[x].call(req, doc, permissions, context);
|
|
4873
5044
|
}
|
|
4874
5045
|
}
|
|
@@ -4888,22 +5059,22 @@ async function collectSchemaFields({
|
|
|
4888
5059
|
for (let x = 0; x < keys2.length; x++) {
|
|
4889
5060
|
const key = keys2[x];
|
|
4890
5061
|
const value = extractScopedOutputRule(permissionSchema, key, access);
|
|
4891
|
-
if ((0,
|
|
5062
|
+
if ((0, import_utils23.isBoolean)(value)) {
|
|
4892
5063
|
if (value) fields.push(key);
|
|
4893
|
-
} else if ((0,
|
|
5064
|
+
} else if ((0, import_utils23.isString)(value)) {
|
|
4894
5065
|
if (stringHandler(value)) fields.push(key);
|
|
4895
|
-
} else if ((0,
|
|
5066
|
+
} else if ((0, import_utils23.isArray)(value)) {
|
|
4896
5067
|
if (arrayHandler(value)) fields.push(key);
|
|
4897
|
-
} else if ((0,
|
|
5068
|
+
} else if ((0, import_utils23.isFunction)(value)) {
|
|
4898
5069
|
if (await value.call(req, ...functionArgs)) fields.push(key);
|
|
4899
5070
|
}
|
|
4900
5071
|
}
|
|
4901
5072
|
return fields;
|
|
4902
5073
|
}
|
|
4903
|
-
var
|
|
5074
|
+
var import_utils23, import_node_util4, permissionFieldOwners;
|
|
4904
5075
|
var init_core_shared = __esm({
|
|
4905
5076
|
"src/core-shared.ts"() {
|
|
4906
|
-
|
|
5077
|
+
import_utils23 = require("@web-ts-toolkit/utils");
|
|
4907
5078
|
import_node_util4 = require("util");
|
|
4908
5079
|
init_helpers();
|
|
4909
5080
|
init_options();
|
|
@@ -5272,8 +5443,8 @@ function equivalentVirtualPopulatePredicate(left, right) {
|
|
|
5272
5443
|
}
|
|
5273
5444
|
if (Array.isArray(left) || Array.isArray(right))
|
|
5274
5445
|
return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((entry, index) => equivalentVirtualPopulatePredicate(entry, right[index]));
|
|
5275
|
-
if ((0,
|
|
5276
|
-
if (!(0,
|
|
5446
|
+
if ((0, import_utils27.isPlainObject)(left) || (0, import_utils27.isPlainObject)(right)) {
|
|
5447
|
+
if (!(0, import_utils27.isPlainObject)(left) || !(0, import_utils27.isPlainObject)(right)) return false;
|
|
5277
5448
|
const a = Object.keys(left), b = Object.keys(right);
|
|
5278
5449
|
return a.length === b.length && a.every(
|
|
5279
5450
|
(key, index) => key === b[index] && equivalentVirtualPopulatePredicate(
|
|
@@ -5344,7 +5515,6 @@ function captureVirtualPopulateRows(batch, inputs, plan, publicPopulate = [], so
|
|
|
5344
5515
|
address,
|
|
5345
5516
|
plan: currentPlan,
|
|
5346
5517
|
refs: /* @__PURE__ */ new Map(),
|
|
5347
|
-
referenceTargets: /* @__PURE__ */ new Map(),
|
|
5348
5518
|
dependencies: /* @__PURE__ */ new Map()
|
|
5349
5519
|
};
|
|
5350
5520
|
row.occurrences.set(addressKey(address), occurrence);
|
|
@@ -5352,7 +5522,6 @@ function captureVirtualPopulateRows(batch, inputs, plan, publicPopulate = [], so
|
|
|
5352
5522
|
const dependencies = (candidate.populateDependencies ?? []).map((dependency) => {
|
|
5353
5523
|
if (!occurrence.refs.has(dependency.path))
|
|
5354
5524
|
occurrence.refs.set(dependency.path, originalRef(value, dependency.path));
|
|
5355
|
-
occurrence.referenceTargets.set(dependency.path, dependency.target);
|
|
5356
5525
|
const request = {
|
|
5357
5526
|
binding: dependency.target,
|
|
5358
5527
|
target: dependency.target,
|
|
@@ -5450,7 +5619,7 @@ async function execute(state) {
|
|
|
5450
5619
|
if (!pending) {
|
|
5451
5620
|
pending = (async () => {
|
|
5452
5621
|
try {
|
|
5453
|
-
if (target.configuration.
|
|
5622
|
+
if (target.configuration.requireOperationAccessForPopulateDependencies !== false && !await targetReadAllowed(state, target))
|
|
5454
5623
|
return void 0;
|
|
5455
5624
|
const parts = await work.hookGate.run(
|
|
5456
5625
|
() => resolveAccessFilterParts({
|
|
@@ -5536,12 +5705,6 @@ function readVirtualPopulateOriginalReference(row, address, path) {
|
|
|
5536
5705
|
function hasVirtualPopulatePublicReference(row, address, path) {
|
|
5537
5706
|
return !!rows.get(row)?.publicRequests.some((request) => addressKey(request.address) === addressKey([...address, path]));
|
|
5538
5707
|
}
|
|
5539
|
-
function isVirtualPopulateReferenceVisible(row, address, path) {
|
|
5540
|
-
const record3 = rows.get(row);
|
|
5541
|
-
const occurrence = record3?.occurrences.get(addressKey(address));
|
|
5542
|
-
const target = occurrence?.refs.get(path)?.present ? occurrence.referenceTargets.get(path) : void 0;
|
|
5543
|
-
return record3 && target ? targetReadAllowed(record3.batch, target) : Promise.resolve(true);
|
|
5544
|
-
}
|
|
5545
5708
|
function readVirtualPopulateInputs(row, address, virtualName) {
|
|
5546
5709
|
const record3 = rows.get(row);
|
|
5547
5710
|
if (!record3?.batch.completed) return { available: false };
|
|
@@ -5665,12 +5828,12 @@ async function loadVirtualPopulateOutputRows(owner, inputs, plan, publicPopulate
|
|
|
5665
5828
|
}
|
|
5666
5829
|
return output;
|
|
5667
5830
|
}
|
|
5668
|
-
var import_mongoose7, import_node_util5,
|
|
5831
|
+
var import_mongoose7, import_node_util5, import_utils27, batches, rows, outputRows, fetchedPublicIdentities, publicViewIdentities, familyRawFetches, addressKey, storage, originalRef, copyOriginalValue, readPolicy, compatible, idKey, logUnavailable;
|
|
5669
5832
|
var init_virtual_populate_execution = __esm({
|
|
5670
5833
|
"src/acl/virtual-populate-execution.ts"() {
|
|
5671
5834
|
import_mongoose7 = require("mongoose");
|
|
5672
5835
|
import_node_util5 = require("util");
|
|
5673
|
-
|
|
5836
|
+
import_utils27 = require("@web-ts-toolkit/utils");
|
|
5674
5837
|
init_cache();
|
|
5675
5838
|
init_core_shared();
|
|
5676
5839
|
init_document();
|
|
@@ -5687,7 +5850,7 @@ var init_virtual_populate_execution = __esm({
|
|
|
5687
5850
|
publicViewIdentities = /* @__PURE__ */ new WeakMap();
|
|
5688
5851
|
familyRawFetches = /* @__PURE__ */ new WeakMap();
|
|
5689
5852
|
addressKey = (address) => JSON.stringify(address);
|
|
5690
|
-
storage = (value) => value instanceof import_mongoose7.Document ? value._doc : (0,
|
|
5853
|
+
storage = (value) => value instanceof import_mongoose7.Document ? value._doc : (0, import_utils27.isPlainObject)(value) ? value : void 0;
|
|
5691
5854
|
originalRef = (source, key) => {
|
|
5692
5855
|
const record3 = storage(source);
|
|
5693
5856
|
return {
|
|
@@ -5700,7 +5863,7 @@ var init_virtual_populate_execution = __esm({
|
|
|
5700
5863
|
const option = getCapturedAuthorizationOption(configuration, `${key}.${access}`);
|
|
5701
5864
|
return key === "operationAccess" || typeof option === "function" ? option : void 0;
|
|
5702
5865
|
});
|
|
5703
|
-
compatible = (a, b) => a.binding.runtime === b.binding.runtime && a.binding.model === b.binding.model && a.binding.schema === b.binding.schema && a.access === b.access && a.requestRead === b.requestRead && a.binding.configuration.
|
|
5866
|
+
compatible = (a, b) => a.binding.runtime === b.binding.runtime && a.binding.model === b.binding.model && a.binding.schema === b.binding.schema && a.access === b.access && a.requestRead === b.requestRead && a.binding.configuration.requireOperationAccessForPopulateDependencies === b.binding.configuration.requireOperationAccessForPopulateDependencies && // Different captures may share only an equivalent terminal persisted binding/policy.
|
|
5704
5867
|
equivalentVirtualPopulatePredicate(
|
|
5705
5868
|
a.binding.configuration.catalog.persistedPaths,
|
|
5706
5869
|
b.binding.configuration.catalog.persistedPaths
|
|
@@ -5714,20 +5877,115 @@ var init_virtual_populate_execution = __esm({
|
|
|
5714
5877
|
});
|
|
5715
5878
|
|
|
5716
5879
|
// src/acl/output-field-filter.ts
|
|
5880
|
+
function callFieldPolicy(authorization, binding) {
|
|
5881
|
+
assertAuthorizationBinding(authorization, binding);
|
|
5882
|
+
let policy = fieldPolicies.get(authorization);
|
|
5883
|
+
if (!policy) {
|
|
5884
|
+
const view = readServiceOutputFieldAuthorization(authorization, binding);
|
|
5885
|
+
policy = {
|
|
5886
|
+
schema: view.permissionSchema,
|
|
5887
|
+
requestPaths: view.permissionSchema == null || (0, import_utils28.isPlainObject)(view.permissionSchema) && Object.isFrozen(view.permissionSchema) ? Object.freeze(Object.keys(view.permissionSchema ?? {})) : void 0,
|
|
5888
|
+
prefix: view.modelPermissionPrefix ?? "",
|
|
5889
|
+
outputFields: view.outputFields,
|
|
5890
|
+
accesses: /* @__PURE__ */ new Map()
|
|
5891
|
+
};
|
|
5892
|
+
if (view.reusable) fieldPolicies.set(authorization, policy);
|
|
5893
|
+
}
|
|
5894
|
+
return policy;
|
|
5895
|
+
}
|
|
5896
|
+
function requestRuleClassification(entry, authorization, permissions, prefix) {
|
|
5897
|
+
if (typeof prefix !== "string") return void 0;
|
|
5898
|
+
let classification = entry.classifications.get(authorization);
|
|
5899
|
+
if (!classification) {
|
|
5900
|
+
classification = prepareRequestFieldRule(entry.rule, permissions, prefix);
|
|
5901
|
+
entry.classifications.set(authorization, classification);
|
|
5902
|
+
}
|
|
5903
|
+
return classification;
|
|
5904
|
+
}
|
|
5905
|
+
function invariantRuleLookup(schema, path) {
|
|
5906
|
+
if (schema == null) return true;
|
|
5907
|
+
if (!(0, import_utils28.isPlainObject)(schema) || !Object.isFrozen(schema)) return false;
|
|
5908
|
+
const exact = Object.getOwnPropertyDescriptor(schema, path);
|
|
5909
|
+
if (exact) {
|
|
5910
|
+
const raw2 = exact.value;
|
|
5911
|
+
return !raw2 || typeof raw2 !== "object" || Array.isArray(raw2) || (0, import_utils28.isPlainObject)(raw2) && Object.isFrozen(raw2);
|
|
5912
|
+
}
|
|
5913
|
+
const [head, ...rest] = path.split(".");
|
|
5914
|
+
const raw = Object.getOwnPropertyDescriptor(schema, head)?.value;
|
|
5915
|
+
if (raw == null) return true;
|
|
5916
|
+
if (!(0, import_utils28.isPlainObject)(raw) || !Object.isFrozen(raw)) return false;
|
|
5917
|
+
const sub = Object.getOwnPropertyDescriptor(raw, "sub");
|
|
5918
|
+
return !rest.length || !sub || invariantRuleLookup(sub.value, rest.join("."));
|
|
5919
|
+
}
|
|
5920
|
+
function prepareOutputPath(policy, authorization, binding, path, access) {
|
|
5921
|
+
let cache = policy.accesses.get(access);
|
|
5922
|
+
if (!cache) {
|
|
5923
|
+
cache = /* @__PURE__ */ new Map();
|
|
5924
|
+
policy.accesses.set(access, cache);
|
|
5925
|
+
}
|
|
5926
|
+
let prepared = cache.get(path);
|
|
5927
|
+
if (!prepared) {
|
|
5928
|
+
const invariant = invariantRuleLookup(policy.schema, path);
|
|
5929
|
+
const permissions = getAuthorizationPermissions(authorization, binding);
|
|
5930
|
+
const entries = extractOutputFieldRuleEntries(policy.schema, path, access).map((entry) => ({
|
|
5931
|
+
...entry,
|
|
5932
|
+
classifications: /* @__PURE__ */ new WeakMap()
|
|
5933
|
+
}));
|
|
5934
|
+
const classifications = entries.map(
|
|
5935
|
+
(entry) => requestRuleClassification(entry, authorization, permissions, policy.prefix)
|
|
5936
|
+
);
|
|
5937
|
+
const backendGrant = hasExplicitFieldGrant(policy.outputFields, path);
|
|
5938
|
+
prepared = {
|
|
5939
|
+
entries,
|
|
5940
|
+
backendGrant,
|
|
5941
|
+
state: backendGrant ? "granted" : classifications.every((value) => value !== void 0) ? combineFieldAuthorizationStates(classifications.map((value) => value.state)) : void 0
|
|
5942
|
+
};
|
|
5943
|
+
if (invariant) cache.set(path, prepared);
|
|
5944
|
+
}
|
|
5945
|
+
return prepared;
|
|
5946
|
+
}
|
|
5947
|
+
function assertOwningOutputDocuments(handle) {
|
|
5948
|
+
const owner = owningDocuments.get(handle);
|
|
5949
|
+
if (owner) {
|
|
5950
|
+
readDocumentAuthorizationAccess(owner.handle, owner.binding);
|
|
5951
|
+
assertOwningOutputDocuments(owner.handle);
|
|
5952
|
+
}
|
|
5953
|
+
}
|
|
5954
|
+
function prepareOutputDocumentAuthorization(authorization, binding, configuration) {
|
|
5955
|
+
const access = readServiceAuthorizationAccess(authorization, binding);
|
|
5956
|
+
const key = `docPermissions.${access.docPermissionsAccess}`;
|
|
5957
|
+
const docPermissions = configuration.docPermissions;
|
|
5958
|
+
const invariant = /^[A-Za-z0-9_-]+$/.test(access.docPermissionsAccess) && (docPermissions == null || (0, import_utils28.isPlainObject)(docPermissions));
|
|
5959
|
+
const option = invariant ? getCapturedAuthorizationOption(configuration, key) : void 0;
|
|
5960
|
+
const hook = typeof option === "function" ? option : void 0;
|
|
5961
|
+
const resolveHook = invariant ? () => hook : () => {
|
|
5962
|
+
const slice = { catalog: configuration.catalog, ...copyAuthorizationValue({ docPermissions }, true) };
|
|
5963
|
+
const option2 = getCapturedAuthorizationOption(slice, key);
|
|
5964
|
+
return typeof option2 === "function" ? option2 : void 0;
|
|
5965
|
+
};
|
|
5966
|
+
return async (args) => {
|
|
5967
|
+
if (args.authorization !== authorization) authorizationError("document resolver call mismatch");
|
|
5968
|
+
assertAuthorizationBinding(authorization, args.binding);
|
|
5969
|
+
return resolveOutputDocumentAuthorizationWithHook(args, access, resolveHook);
|
|
5970
|
+
};
|
|
5971
|
+
}
|
|
5717
5972
|
async function resolveOutputDocumentAuthorization(args) {
|
|
5973
|
+
const configuration = readServiceDocumentPermissions(args.authorization, args.binding);
|
|
5974
|
+
return prepareOutputDocumentAuthorization(args.authorization, args.binding, configuration)(args);
|
|
5975
|
+
}
|
|
5976
|
+
async function resolveOutputDocumentAuthorizationWithHook(args, access, resolveHook) {
|
|
5718
5977
|
const { authorization, binding } = args;
|
|
5719
|
-
const { configuration, access } = readServiceAuthorization(authorization, binding);
|
|
5720
5978
|
const stage = args.stage ?? createDocumentAuthorizationStage(authorization, binding, args.snapshot);
|
|
5721
5979
|
if (args.stage) assertDocumentAuthorizationStage(stage, authorization, binding, args.snapshot);
|
|
5722
5980
|
const handle = await resolveDocumentAuthorization(stage, async function(doc, permissions) {
|
|
5723
5981
|
if (args.owningDocument) return readDocumentAuthorization(args.owningDocument, args.owningBinding).grants;
|
|
5724
5982
|
if (args.knownOutput) return {};
|
|
5725
|
-
const hook =
|
|
5726
|
-
if (
|
|
5983
|
+
const hook = resolveHook();
|
|
5984
|
+
if (!hook) return {};
|
|
5727
5985
|
try {
|
|
5728
5986
|
const run = () => hook.call(this, doc, permissions, args.context);
|
|
5729
5987
|
const grants = await getRequestWorkState(binding.request, binding.runtime).hookGate.run(run);
|
|
5730
|
-
return (0,
|
|
5988
|
+
return (0, import_utils28.isPlainObject)(grants) ? grants : {};
|
|
5731
5989
|
} catch (error2) {
|
|
5732
5990
|
warn("docPermissions hook failed; applying empty document permissions", {
|
|
5733
5991
|
modelName: binding.modelName,
|
|
@@ -5744,6 +6002,7 @@ async function resolveOutputDocumentAuthorization(args) {
|
|
|
5744
6002
|
return handle;
|
|
5745
6003
|
}
|
|
5746
6004
|
function evaluateRequestRule(handle, binding, entry, prefix, access) {
|
|
6005
|
+
assertOwningOutputDocuments(handle);
|
|
5747
6006
|
const owner = owningDocuments.get(handle);
|
|
5748
6007
|
if (owner && !entry.path.startsWith(`${(binding.scopePath ?? []).join(".")}.`)) {
|
|
5749
6008
|
return evaluateRequestRule(owner.handle, owner.binding, entry, prefix, access);
|
|
@@ -5752,65 +6011,78 @@ function evaluateRequestRule(handle, binding, entry, prefix, access) {
|
|
|
5752
6011
|
handle,
|
|
5753
6012
|
binding,
|
|
5754
6013
|
`request:${access}:${entry.path}`,
|
|
5755
|
-
function(permissions, grants) {
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
6014
|
+
async function(permissions, grants) {
|
|
6015
|
+
const { authorization } = readDocumentAuthorizationAccess(handle, binding);
|
|
6016
|
+
const classification = requestRuleClassification(entry, authorization, permissions, prefix);
|
|
6017
|
+
let allowed = classification?.decision;
|
|
6018
|
+
if (allowed === void 0) {
|
|
6019
|
+
allowed = await evaluateScopedAccessRule({
|
|
6020
|
+
req: this,
|
|
6021
|
+
rule: entry.rule,
|
|
6022
|
+
globalPermissions: permissions,
|
|
6023
|
+
docPermissions: grants,
|
|
6024
|
+
modelPermissionPrefix: prefix
|
|
6025
|
+
});
|
|
6026
|
+
}
|
|
6027
|
+
assertOwningOutputDocuments(handle);
|
|
6028
|
+
return allowed;
|
|
5763
6029
|
}
|
|
5764
6030
|
);
|
|
5765
6031
|
}
|
|
5766
6032
|
function evaluateAuthorizedOutputField(handle, binding, field) {
|
|
5767
|
-
const { authorization } =
|
|
5768
|
-
|
|
6033
|
+
const { authorization } = readDocumentAuthorizationAccess(handle, binding);
|
|
6034
|
+
assertOwningOutputDocuments(handle);
|
|
5769
6035
|
const path = [...binding.scopePath ?? [], field].join(".");
|
|
5770
|
-
const
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
const args = {
|
|
6036
|
+
const decision = memoizeDocumentFieldDecision(handle, binding, `output:${path}`, async function(permissions) {
|
|
6037
|
+
const policy = callFieldPolicy(authorization, binding);
|
|
6038
|
+
const { outputAccess } = readDocumentAuthorizationAccess(handle, binding);
|
|
6039
|
+
const prepared = prepareOutputPath(policy, authorization, binding, path, outputAccess);
|
|
6040
|
+
const unresolved = unresolvedDocuments.has(handle);
|
|
6041
|
+
const state = unresolved ? prepared.state ?? classifyEffectiveFieldAuthorization({
|
|
5777
6042
|
path,
|
|
5778
|
-
rules: entries.map((entry) => entry.rule),
|
|
6043
|
+
rules: prepared.entries.map((entry) => entry.rule),
|
|
6044
|
+
modelPermissionPrefix: policy.prefix,
|
|
5779
6045
|
outputFields: policy.outputFields,
|
|
5780
|
-
globalPermissions: permissions
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
if (
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
6046
|
+
globalPermissions: permissions
|
|
6047
|
+
}) : void 0;
|
|
6048
|
+
let allowed;
|
|
6049
|
+
if (unresolved && state !== "granted") allowed = false;
|
|
6050
|
+
else if (prepared.backendGrant) allowed = true;
|
|
6051
|
+
else {
|
|
6052
|
+
allowed = true;
|
|
6053
|
+
for (const entry of prepared.entries) {
|
|
6054
|
+
if (!await evaluateRequestRule(handle, binding, entry, policy.prefix, outputAccess)) {
|
|
6055
|
+
allowed = false;
|
|
6056
|
+
break;
|
|
6057
|
+
}
|
|
6058
|
+
}
|
|
6059
|
+
}
|
|
6060
|
+
assertOwningOutputDocuments(handle);
|
|
6061
|
+
return allowed;
|
|
5790
6062
|
});
|
|
6063
|
+
return owningDocuments.has(handle) ? decision.then((allowed) => {
|
|
6064
|
+
assertOwningOutputDocuments(handle);
|
|
6065
|
+
return allowed;
|
|
6066
|
+
}) : decision;
|
|
5791
6067
|
}
|
|
5792
6068
|
async function requestOutputFieldPaths(handle, binding, access) {
|
|
5793
|
-
const { authorization } =
|
|
5794
|
-
|
|
5795
|
-
const
|
|
6069
|
+
const { authorization } = readDocumentAuthorizationAccess(handle, binding);
|
|
6070
|
+
assertOwningOutputDocuments(handle);
|
|
6071
|
+
const policy = callFieldPolicy(authorization, binding);
|
|
5796
6072
|
const fields = [];
|
|
5797
|
-
for (const path of Object.keys(schema ?? {})) {
|
|
5798
|
-
const entries =
|
|
6073
|
+
for (const path of policy.requestPaths ?? Object.keys(policy.schema ?? {})) {
|
|
6074
|
+
const { entries } = prepareOutputPath(policy, authorization, binding, path, access);
|
|
5799
6075
|
let allowed = true;
|
|
5800
6076
|
for (const entry of entries) {
|
|
5801
|
-
if (!await evaluateRequestRule(
|
|
5802
|
-
handle,
|
|
5803
|
-
binding,
|
|
5804
|
-
entry,
|
|
5805
|
-
configuration.modelPermissionPrefix ?? "",
|
|
5806
|
-
access
|
|
5807
|
-
)) {
|
|
6077
|
+
if (!await evaluateRequestRule(handle, binding, entry, policy.prefix, access)) {
|
|
5808
6078
|
allowed = false;
|
|
5809
6079
|
break;
|
|
5810
6080
|
}
|
|
5811
6081
|
}
|
|
5812
6082
|
if (allowed && entries.length) fields.push(path);
|
|
5813
6083
|
}
|
|
6084
|
+
assertOwningOutputDocuments(handle);
|
|
6085
|
+
readDocumentAuthorizationAccess(handle, binding);
|
|
5814
6086
|
return fields;
|
|
5815
6087
|
}
|
|
5816
6088
|
function authorizeEmbeddedOutputPlan(parent, child) {
|
|
@@ -5831,24 +6103,24 @@ function authorizeEmbeddedOutputPlan(parent, child) {
|
|
|
5831
6103
|
function hasWholeOutputValueGrant(plan, field) {
|
|
5832
6104
|
if (plan.fieldStates?.[field] !== "granted") return false;
|
|
5833
6105
|
const binding = plan.authorizationBinding;
|
|
5834
|
-
const {
|
|
5835
|
-
return hasExplicitFieldGrant(
|
|
6106
|
+
const { outputFields } = readServiceOutputPolicy(plan.authorization, binding);
|
|
6107
|
+
return hasExplicitFieldGrant(outputFields, [...binding.scopePath ?? [], field].join("."));
|
|
5836
6108
|
}
|
|
5837
6109
|
function copyOutputValue(value, plan, path) {
|
|
5838
|
-
const {
|
|
5839
|
-
const virtualValue =
|
|
5840
|
-
const opaque =
|
|
6110
|
+
const { catalog } = readServiceOutputPolicy(plan.authorization, plan.authorizationBinding);
|
|
6111
|
+
const virtualValue = catalog.virtualPaths?.some((p) => matchesCatalogPattern(p, path));
|
|
6112
|
+
const opaque = catalog.opaquePaths?.some((p) => matchesCatalogPattern(p, path));
|
|
5841
6113
|
const excluded = plan.effectiveSelectNorm.filter((token) => token.startsWith("-")).map((token) => [...plan.authorizationBinding.scopePath ?? [], token.slice(1)].join("."));
|
|
5842
6114
|
const visit = (input, current) => {
|
|
5843
6115
|
if (Array.isArray(input)) return input.map((entry) => visit(entry, current));
|
|
5844
6116
|
if (input instanceof Map) return visit(Object.fromEntries(input), current);
|
|
5845
|
-
if (!(0,
|
|
6117
|
+
if (!(0, import_utils28.isPlainObject)(input)) return deepIsolateValue(input);
|
|
5846
6118
|
const output = {};
|
|
5847
6119
|
for (const [key, entry] of Object.entries(input)) {
|
|
5848
6120
|
const child = `${current}.${key}`;
|
|
5849
6121
|
if (excluded.some((entry2) => child === entry2 || child.startsWith(`${entry2}.`))) continue;
|
|
5850
6122
|
const safeValueKey = !["__proto__", "constructor", "prototype", "_doc", "$__", "__v"].includes(key);
|
|
5851
|
-
if (!(opaque ? safeValueKey : isSafeOutputPath(key)) ||
|
|
6123
|
+
if (!(opaque ? safeValueKey : isSafeOutputPath(key)) || catalog.protectedPaths?.some((p) => matchesCatalogPattern(p, child, true)) || !opaque && !virtualValue && !isCatalogOutputPath(catalog, child))
|
|
5852
6124
|
continue;
|
|
5853
6125
|
output[key] = visit(entry, child);
|
|
5854
6126
|
}
|
|
@@ -5858,25 +6130,21 @@ function copyOutputValue(value, plan, path) {
|
|
|
5858
6130
|
}
|
|
5859
6131
|
function copyAuthorizedReference(value, plan, path) {
|
|
5860
6132
|
if (Array.isArray(value)) return value.map((entry) => copyAuthorizedReference(entry, plan, path));
|
|
5861
|
-
if (!(0,
|
|
6133
|
+
if (!(0, import_utils28.isPlainObject)(value)) return deepIsolateValue(value);
|
|
5862
6134
|
const handle = getAssociatedDocumentAuthorization(value, plan.authorization);
|
|
5863
6135
|
if (handle) {
|
|
5864
6136
|
const copy = deepIsolateValue(value);
|
|
5865
6137
|
transferDocumentAuthorizationGraph(value, copy);
|
|
5866
6138
|
return copy;
|
|
5867
6139
|
}
|
|
5868
|
-
const { relatedTargets } = readServiceAuthorization(plan.authorization, plan.authorizationBinding);
|
|
5869
|
-
if (relatedTargets.some((target) => target.path === path && target.kind === "passthrough")) {
|
|
5870
|
-
return deepIsolateValue(value);
|
|
5871
|
-
}
|
|
5872
6140
|
return Object.prototype.hasOwnProperty.call(value, "_id") ? deepIsolateValue(value._id) : void 0;
|
|
5873
6141
|
}
|
|
5874
6142
|
function retainOutputMetadata(output, source, configuration, scope2) {
|
|
5875
6143
|
if (scope2.length || configuration.stripPermissionsField) return;
|
|
5876
6144
|
const parts = (configuration.documentPermissionField ?? "_permissions").split(".");
|
|
5877
6145
|
let value = source;
|
|
5878
|
-
for (const part of parts) value = (0,
|
|
5879
|
-
if (!(0,
|
|
6146
|
+
for (const part of parts) value = (0, import_utils28.isPlainObject)(value) ? value[part] : void 0;
|
|
6147
|
+
if (!(0, import_utils28.isPlainObject)(value)) return;
|
|
5880
6148
|
const keys2 = configuration.exposedDocPermissionKeys;
|
|
5881
6149
|
const metadata = Object.fromEntries(
|
|
5882
6150
|
Object.entries(value).filter(
|
|
@@ -5886,7 +6154,7 @@ function retainOutputMetadata(output, source, configuration, scope2) {
|
|
|
5886
6154
|
const copy = { ...output };
|
|
5887
6155
|
let target = copy;
|
|
5888
6156
|
for (const part of parts.slice(0, -1)) {
|
|
5889
|
-
target[part] = (0,
|
|
6157
|
+
target[part] = (0, import_utils28.isPlainObject)(target[part]) ? { ...target[part] } : {};
|
|
5890
6158
|
target = target[part];
|
|
5891
6159
|
}
|
|
5892
6160
|
target[parts[parts.length - 1]] = deepIsolateValue(metadata);
|
|
@@ -5928,11 +6196,11 @@ async function filterExistingOutput(source, plan, handle, associated) {
|
|
|
5928
6196
|
for (const entry of value2) values.push(await one(entry) ?? null);
|
|
5929
6197
|
return values;
|
|
5930
6198
|
}
|
|
5931
|
-
if (!(0,
|
|
6199
|
+
if (!(0, import_utils28.isPlainObject)(value2)) return value2 === null ? null : void 0;
|
|
5932
6200
|
const childHandle = associated ? getAssociatedDocumentAuthorization(value2) : void 0;
|
|
5933
6201
|
let child = scoped;
|
|
5934
6202
|
if (childHandle) {
|
|
5935
|
-
const state =
|
|
6203
|
+
const state = readDocumentAuthorizationAccess(childHandle, scoped.authorizationBinding);
|
|
5936
6204
|
if (getAuthorizationProvenance(state.authorization) !== getAuthorizationProvenance(plan.authorization))
|
|
5937
6205
|
authorizationError("child call mismatch");
|
|
5938
6206
|
child = helperPlan(state.authorization, scoped.authorizationBinding);
|
|
@@ -5996,7 +6264,7 @@ async function filterModelOutputForHelper(args) {
|
|
|
5996
6264
|
if (normalized.kind === "document") {
|
|
5997
6265
|
const { documentAuthorization: handle2, binding: binding2 } = normalized;
|
|
5998
6266
|
assertDocumentAuthorization(handle2, { binding: binding2, output: args.doc, outputAccess: access });
|
|
5999
|
-
const state =
|
|
6267
|
+
const state = readDocumentAuthorizationAccess(handle2, binding2);
|
|
6000
6268
|
return filterExistingOutput(
|
|
6001
6269
|
args.doc,
|
|
6002
6270
|
helperPlan(state.authorization, binding2),
|
|
@@ -6008,7 +6276,7 @@ async function filterModelOutputForHelper(args) {
|
|
|
6008
6276
|
const plan = helperPlan(normalized.authorization, binding);
|
|
6009
6277
|
if (args.doc == null) return { output: args.doc, fields: [] };
|
|
6010
6278
|
const source = isolateDocForOutput(args.doc);
|
|
6011
|
-
if (!(0,
|
|
6279
|
+
if (!(0, import_utils28.isPlainObject)(source)) return authorizationError("output helper requires one plain or hydrated document");
|
|
6012
6280
|
const knownOutput = !!args.doc && typeof args.doc === "object" && isKnownAuthorizationOutput(args.doc);
|
|
6013
6281
|
const handle = await resolveOutputDocumentAuthorization({
|
|
6014
6282
|
authorization: normalized.authorization,
|
|
@@ -6019,10 +6287,10 @@ async function filterModelOutputForHelper(args) {
|
|
|
6019
6287
|
});
|
|
6020
6288
|
return filterExistingOutput(source, plan, handle, false);
|
|
6021
6289
|
}
|
|
6022
|
-
var
|
|
6290
|
+
var import_utils28, unresolvedDocuments, owningDocuments, fieldPolicies;
|
|
6023
6291
|
var init_output_field_filter = __esm({
|
|
6024
6292
|
"src/acl/output-field-filter.ts"() {
|
|
6025
|
-
|
|
6293
|
+
import_utils28 = require("@web-ts-toolkit/utils");
|
|
6026
6294
|
init_permissions_alias();
|
|
6027
6295
|
init_document();
|
|
6028
6296
|
init_request_work();
|
|
@@ -6036,6 +6304,7 @@ var init_output_field_filter = __esm({
|
|
|
6036
6304
|
init_output_projection();
|
|
6037
6305
|
unresolvedDocuments = /* @__PURE__ */ new WeakSet();
|
|
6038
6306
|
owningDocuments = /* @__PURE__ */ new WeakMap();
|
|
6307
|
+
fieldPolicies = /* @__PURE__ */ new WeakMap();
|
|
6039
6308
|
}
|
|
6040
6309
|
});
|
|
6041
6310
|
|
|
@@ -6104,27 +6373,53 @@ __export(finalize_model_output_exports, {
|
|
|
6104
6373
|
finalizeModelOutput: () => finalizeModelOutput,
|
|
6105
6374
|
finalizeModelOutputs: () => finalizeModelOutputs
|
|
6106
6375
|
});
|
|
6107
|
-
|
|
6108
|
-
const scopePath = args.scopePath;
|
|
6376
|
+
function assertFinalizerCall(args, prepared) {
|
|
6109
6377
|
const plan = args.plan;
|
|
6110
6378
|
const binding = plan.authorizationBinding;
|
|
6111
|
-
|
|
6112
|
-
if (plan.authorization &&
|
|
6379
|
+
if (plan.authorization !== prepared.authorization) authorizationError("finalizer call changed during pass");
|
|
6380
|
+
if (plan.authorization && binding) assertAuthorizationBinding(plan.authorization, binding);
|
|
6381
|
+
const access = prepared.policy?.access;
|
|
6382
|
+
if (plan.authorization && (!binding || binding.request !== args.request || binding.modelName !== args.receivingModelName || access?.virtualAccess !== args.virtualAccess || access.outputAccess !== args.outputAccess || access.docPermissionsAccess !== args.docPermissionsAccess || (binding.scopePath ?? []).join(".") !== args.scopePath.filter((p) => p !== "sub").join("."))) {
|
|
6113
6383
|
authorizationError("finalizer call/model/scope/access mismatch");
|
|
6114
6384
|
}
|
|
6115
|
-
|
|
6385
|
+
}
|
|
6386
|
+
function prepareFinalizer(args, sharedContext = false) {
|
|
6387
|
+
const { authorization, authorizationBinding: binding } = args.plan;
|
|
6388
|
+
const policy = authorization && binding ? readServiceOutputPolicy(authorization, binding) : void 0;
|
|
6389
|
+
assertFinalizerCall(args, { authorization, policy });
|
|
6390
|
+
const configuration = authorization ? readServiceFinalizerConfiguration(authorization, binding) : void 0;
|
|
6391
|
+
const snapshot = configuration ? configuration : deepIsolateValue(args.snapshot);
|
|
6392
|
+
return {
|
|
6393
|
+
authorization,
|
|
6394
|
+
policy,
|
|
6395
|
+
snapshot,
|
|
6396
|
+
baseContext: deepIsolateValue(args.context ?? {}),
|
|
6397
|
+
sharedContext,
|
|
6398
|
+
scopeVirtualNames: getScopeVirtualNames(snapshot, args.scopePath),
|
|
6399
|
+
scopedSchema: configuration ? null : getScopedPermissionSchema2(snapshot.permissionSchema, args.scopePath),
|
|
6400
|
+
permissions: authorization ? getAuthorizationPermissions(authorization, binding) : void 0,
|
|
6401
|
+
resolveDocument: authorization ? prepareOutputDocumentAuthorization(authorization, binding, configuration) : void 0
|
|
6402
|
+
};
|
|
6403
|
+
}
|
|
6404
|
+
async function finalizeSingleDoc(args, input, prepared) {
|
|
6405
|
+
assertFinalizerCall(args, prepared);
|
|
6406
|
+
const scopePath = args.scopePath;
|
|
6407
|
+
const plan = args.plan;
|
|
6408
|
+
const binding = plan.authorizationBinding;
|
|
6409
|
+
const captured = prepared.policy;
|
|
6410
|
+
const snapshot = prepared.snapshot;
|
|
6116
6411
|
const limit = args.resolvedLimit;
|
|
6117
6412
|
const gate = args.sharedGate;
|
|
6118
6413
|
const original = getIncludeOriginal(input);
|
|
6119
6414
|
const privateRow = args.virtualPopulateRow ?? (original && typeof original === "object" ? getVirtualPopulateRow(original) : void 0);
|
|
6120
6415
|
const privateAddress = args.virtualPopulateAddress ?? [];
|
|
6121
6416
|
const isolated = isolateDocForOutput(input);
|
|
6122
|
-
const output = (0,
|
|
6123
|
-
if (captured && (0,
|
|
6417
|
+
const output = (0, import_utils29.isPlainObject)(isolated) ? isolated : {};
|
|
6418
|
+
if (captured && (0, import_utils29.isPlainObject)(input))
|
|
6124
6419
|
for (const key of Object.keys(output)) {
|
|
6125
6420
|
transferDocumentAuthorizationGraph(input[key], output[key]);
|
|
6126
6421
|
}
|
|
6127
|
-
const baseContext =
|
|
6422
|
+
const baseContext = prepared.sharedContext ? deepIsolateValue(prepared.baseContext) : prepared.baseContext;
|
|
6128
6423
|
const operation = captured?.access.operation ?? baseContext.operation ?? args.operation ?? args.virtualAccess;
|
|
6129
6424
|
const scopeContext = {
|
|
6130
6425
|
...baseContext,
|
|
@@ -6142,7 +6437,7 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6142
6437
|
if (captured) {
|
|
6143
6438
|
const projected = args.documentAuthorizationStage ? input : deepIsolateValue(output);
|
|
6144
6439
|
metadataSource = deepIsolateValue(output);
|
|
6145
|
-
documentAuthorization = await
|
|
6440
|
+
documentAuthorization = await prepared.resolveDocument({
|
|
6146
6441
|
authorization: plan.authorization,
|
|
6147
6442
|
binding,
|
|
6148
6443
|
snapshot: projected,
|
|
@@ -6155,13 +6450,10 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6155
6450
|
}
|
|
6156
6451
|
const docGrants = documentAuthorization ? readDocumentAuthorization(documentAuthorization, binding).grants : await resolveDocPermissions(args, output, scopeContext);
|
|
6157
6452
|
scopeContext.docPermissions = deepIsolateValue(docGrants);
|
|
6158
|
-
const globalPerms =
|
|
6159
|
-
const modelPermissionPrefix = snapshot.modelPermissionPrefix ?? "";
|
|
6160
|
-
const documentPermissionField = snapshot.documentPermissionField ?? "_permissions";
|
|
6161
|
-
const scopedSchema =
|
|
6162
|
-
snapshot.permissionSchema ?? null,
|
|
6163
|
-
scopePath
|
|
6164
|
-
);
|
|
6453
|
+
const globalPerms = prepared.permissions ?? resolveGlobalPermissions(args);
|
|
6454
|
+
const modelPermissionPrefix = captured ? "" : deepIsolateValue(snapshot.modelPermissionPrefix ?? "");
|
|
6455
|
+
const documentPermissionField = captured ? "_permissions" : deepIsolateValue(snapshot.documentPermissionField ?? "_permissions");
|
|
6456
|
+
const scopedSchema = deepIsolateValue(prepared.scopedSchema);
|
|
6165
6457
|
const childPlans = plan.childPlans ?? {};
|
|
6166
6458
|
for (const [containerName, childPlan] of Object.entries(childPlans)) {
|
|
6167
6459
|
if (!(containerName in output)) continue;
|
|
@@ -6175,17 +6467,18 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6175
6467
|
);
|
|
6176
6468
|
continue;
|
|
6177
6469
|
}
|
|
6178
|
-
if (captured && !(0,
|
|
6470
|
+
if (captured && !(0, import_utils29.isPlainObject)(rawContainer) && !Array.isArray(rawContainer)) {
|
|
6179
6471
|
delete output[containerName];
|
|
6180
6472
|
continue;
|
|
6181
6473
|
}
|
|
6182
6474
|
retainRawAssociation(output, containerName, rawContainer);
|
|
6183
|
-
const childSnapshot = snapshot;
|
|
6184
6475
|
const childBase = {
|
|
6185
6476
|
...args,
|
|
6186
6477
|
scopePath: [...childPlan.scopePath ?? [...scopePath, containerName, "sub"]],
|
|
6187
6478
|
plan: captured ? authorizeEmbeddedOutputPlan(plan, childPlan) : childPlan,
|
|
6188
|
-
|
|
6479
|
+
// Authenticated preparation reads its own authority. Do not clone an
|
|
6480
|
+
// otherwise unused public configuration graph on default traversal.
|
|
6481
|
+
snapshot: args.snapshot,
|
|
6189
6482
|
// Embedded reuses the owning parent's grants + accesses (VIRT-00A D2).
|
|
6190
6483
|
docPermissions: docGrants,
|
|
6191
6484
|
context: scopeContext,
|
|
@@ -6196,10 +6489,11 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6196
6489
|
related: [],
|
|
6197
6490
|
virtualPopulateRow: privateRow
|
|
6198
6491
|
};
|
|
6492
|
+
let childPreparation;
|
|
6199
6493
|
const finalizeOneChild = async (rawChild, address) => {
|
|
6200
6494
|
if (captured && Array.isArray(rawChild))
|
|
6201
6495
|
return mapWithConcurrencyLimit(rawChild, limit, (entry, index) => finalizeOneChild(entry, [...address, index]));
|
|
6202
|
-
if (!(0,
|
|
6496
|
+
if (!(0, import_utils29.isPlainObject)(rawChild) && !Array.isArray(rawChild)) return captured ? null : deepIsolateValue(rawChild);
|
|
6203
6497
|
if (args.traversal?.finalizeEmbeddedChildren) {
|
|
6204
6498
|
return args.traversal.finalizeEmbeddedChildren({
|
|
6205
6499
|
containerName,
|
|
@@ -6216,7 +6510,14 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6216
6510
|
} : { ...args, virtualPopulateRow: privateRow, virtualPopulateAddress: address }
|
|
6217
6511
|
});
|
|
6218
6512
|
}
|
|
6219
|
-
return finalizeSingleDoc(
|
|
6513
|
+
return finalizeSingleDoc(
|
|
6514
|
+
{ ...childBase, virtualPopulateAddress: address },
|
|
6515
|
+
rawChild,
|
|
6516
|
+
childPreparation ??= prepareFinalizer(
|
|
6517
|
+
childBase,
|
|
6518
|
+
Array.isArray(rawContainer) && (rawContainer.length > 1 || Array.isArray(rawContainer[0]))
|
|
6519
|
+
)
|
|
6520
|
+
);
|
|
6220
6521
|
};
|
|
6221
6522
|
if (Array.isArray(rawContainer)) {
|
|
6222
6523
|
const finalized = await mapWithConcurrencyLimit(
|
|
@@ -6225,7 +6526,7 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6225
6526
|
(entry, index) => finalizeOneChild(entry, [...privateAddress, containerName, index])
|
|
6226
6527
|
);
|
|
6227
6528
|
output[containerName] = finalized;
|
|
6228
|
-
} else if ((0,
|
|
6529
|
+
} else if ((0, import_utils29.isPlainObject)(rawContainer)) {
|
|
6229
6530
|
output[containerName] = await finalizeOneChild(rawContainer, [
|
|
6230
6531
|
...privateAddress,
|
|
6231
6532
|
containerName
|
|
@@ -6237,8 +6538,8 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6237
6538
|
let rawRelated;
|
|
6238
6539
|
let originalRelated;
|
|
6239
6540
|
try {
|
|
6240
|
-
rawRelated = target.path.includes(".") ? (0,
|
|
6241
|
-
originalRelated = (0,
|
|
6541
|
+
rawRelated = target.path.includes(".") ? (0, import_utils29.get)(output, target.path) : output[target.path];
|
|
6542
|
+
originalRelated = (0, import_utils29.get)(original, target.path);
|
|
6242
6543
|
} catch {
|
|
6243
6544
|
continue;
|
|
6244
6545
|
}
|
|
@@ -6268,8 +6569,9 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6268
6569
|
context: scopeContext,
|
|
6269
6570
|
related: target.plan.relatedPlans?.length ? (args.related ?? []).filter((entry) => entry.path.startsWith(`${target.path}.`)) : []
|
|
6270
6571
|
};
|
|
6572
|
+
let relatedPreparation;
|
|
6271
6573
|
const finalizeOneRelated = async (rawChild, originalChild = rawChild) => {
|
|
6272
|
-
if (!(0,
|
|
6574
|
+
if (!(0, import_utils29.isPlainObject)(rawChild) && !Array.isArray(rawChild)) return rawChild;
|
|
6273
6575
|
if (typeof rawChild?._bsontype === "string") return rawChild;
|
|
6274
6576
|
const childOriginal = getIncludeOriginal(originalChild);
|
|
6275
6577
|
const childRow = childOriginal && typeof childOriginal === "object" ? getVirtualPopulateRow(childOriginal) : void 0;
|
|
@@ -6281,7 +6583,11 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6281
6583
|
parentArgs: { ...args, virtualPopulateRow: childRow, virtualPopulateAddress: [] }
|
|
6282
6584
|
});
|
|
6283
6585
|
}
|
|
6284
|
-
return finalizeSingleDoc(
|
|
6586
|
+
return finalizeSingleDoc(
|
|
6587
|
+
{ ...relatedBase, virtualPopulateRow: childRow },
|
|
6588
|
+
rawChild,
|
|
6589
|
+
relatedPreparation ??= prepareFinalizer(relatedBase, Array.isArray(rawRelated) && rawRelated.length > 1)
|
|
6590
|
+
);
|
|
6285
6591
|
};
|
|
6286
6592
|
let finalized;
|
|
6287
6593
|
if (Array.isArray(rawRelated)) {
|
|
@@ -6290,29 +6596,35 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6290
6596
|
limit,
|
|
6291
6597
|
(entry, index) => finalizeOneRelated(entry, Array.isArray(originalRelated) ? originalRelated[index] : void 0)
|
|
6292
6598
|
);
|
|
6293
|
-
} else if ((0,
|
|
6599
|
+
} else if ((0, import_utils29.isPlainObject)(rawRelated)) {
|
|
6294
6600
|
finalized = await finalizeOneRelated(rawRelated, originalRelated);
|
|
6295
6601
|
} else {
|
|
6296
6602
|
continue;
|
|
6297
6603
|
}
|
|
6298
6604
|
try {
|
|
6299
|
-
if (target.path.includes(".")) (0,
|
|
6605
|
+
if (target.path.includes(".")) (0, import_utils29.set)(output, target.path, finalized);
|
|
6300
6606
|
else output[target.path] = finalized;
|
|
6301
6607
|
} catch {
|
|
6302
6608
|
}
|
|
6303
6609
|
}
|
|
6304
|
-
const
|
|
6305
|
-
for (const virtualName of scopeVirtualNames) {
|
|
6610
|
+
for (const virtualName of prepared.scopeVirtualNames) {
|
|
6306
6611
|
if (virtualName in output) delete output[virtualName];
|
|
6307
6612
|
}
|
|
6308
|
-
const stableBase = deepIsolateValue(output);
|
|
6309
|
-
const scopeLabel = scopePath.length > 0 ? scopePath.join(".") : "";
|
|
6310
6613
|
const candidates = plan.candidates ?? [];
|
|
6614
|
+
const needsGetterView = candidates.some((candidate) => {
|
|
6615
|
+
const descriptor = candidate.descriptor;
|
|
6616
|
+
if (typeof descriptor?.get !== "function") return false;
|
|
6617
|
+
if (!privateRow && descriptor.dependsOnPopulate?.length) return false;
|
|
6618
|
+
const dependsOn = Array.isArray(descriptor.dependsOn) ? descriptor.dependsOn : [];
|
|
6619
|
+
return dependsOn.every((dep) => typeof dep === "string" && !isAbsentDependency(output, dep));
|
|
6620
|
+
});
|
|
6621
|
+
let stableBase = needsGetterView ? deepIsolateValue(output) : void 0;
|
|
6622
|
+
const scopeLabel = scopePath.length > 0 ? scopePath.join(".") : "";
|
|
6311
6623
|
const staged = /* @__PURE__ */ new Map();
|
|
6312
6624
|
const runCandidate = async (candidate) => {
|
|
6313
6625
|
const dependsOn = Array.isArray(candidate.descriptor?.dependsOn) ? candidate.descriptor.dependsOn : [];
|
|
6314
6626
|
for (const dep of dependsOn) {
|
|
6315
|
-
if (typeof dep !== "string" || isAbsentDependency(stableBase, dep)) return;
|
|
6627
|
+
if (typeof dep !== "string" || isAbsentDependency(stableBase ?? output, dep)) return;
|
|
6316
6628
|
}
|
|
6317
6629
|
const allowed = documentAuthorization ? await evaluateAuthorizedOutputField(documentAuthorization, binding, candidate.name) : await evaluateEffectiveFieldAuthorization({
|
|
6318
6630
|
req: args.request,
|
|
@@ -6327,9 +6639,9 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6327
6639
|
if (typeof getter !== "function") return;
|
|
6328
6640
|
const privateInputs = privateRow ? readVirtualPopulateInputs(privateRow, privateAddress, candidate.name) : candidate.descriptor.dependsOnPopulate?.length ? { available: false } : { available: true, populated: {} };
|
|
6329
6641
|
if (!privateInputs.available) return;
|
|
6330
|
-
const isolatedView = deepIsolateValue(stableBase);
|
|
6642
|
+
const isolatedView = deepIsolateValue(stableBase ??= deepIsolateValue(output));
|
|
6331
6643
|
const virtualContext = {
|
|
6332
|
-
...scopeContext,
|
|
6644
|
+
...deepIsolateValue(scopeContext),
|
|
6333
6645
|
docPermissions: deepIsolateValue(docGrants)
|
|
6334
6646
|
};
|
|
6335
6647
|
const outcome = await runVirtualGetter({
|
|
@@ -6410,7 +6722,6 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6410
6722
|
if (!captured && documentPermissionField in output) keep.add(documentPermissionField);
|
|
6411
6723
|
const trimmed = {};
|
|
6412
6724
|
for (const key of keep) {
|
|
6413
|
-
if (privateRow && !await isVirtualPopulateReferenceVisible(privateRow, privateAddress, key)) continue;
|
|
6414
6725
|
if (privateRow && !hasVirtualPopulatePublicReference(privateRow, privateAddress, key)) {
|
|
6415
6726
|
const ref = readVirtualPopulateOriginalReference(privateRow, privateAddress, key);
|
|
6416
6727
|
if (ref) {
|
|
@@ -6421,12 +6732,25 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6421
6732
|
if (!(key in output)) continue;
|
|
6422
6733
|
if (captured && !plan.childPlans[key]) {
|
|
6423
6734
|
const path = [...binding.scopePath ?? [], key].join(".");
|
|
6424
|
-
trimmed[key] = captured.
|
|
6735
|
+
trimmed[key] = captured.catalog.referencePaths?.some((p) => matchesCatalogPattern(p, path)) ? copyAuthorizedReference(output[key], plan, path) : copyOutputValue(output[key], plan, path);
|
|
6425
6736
|
if (trimmed[key] === void 0) delete trimmed[key];
|
|
6426
6737
|
} else trimmed[key] = output[key];
|
|
6427
6738
|
}
|
|
6428
6739
|
if (documentAuthorization) {
|
|
6429
|
-
retainOutputMetadata(
|
|
6740
|
+
retainOutputMetadata(
|
|
6741
|
+
trimmed,
|
|
6742
|
+
metadataSource,
|
|
6743
|
+
copyAuthorizationValue(
|
|
6744
|
+
{
|
|
6745
|
+
documentPermissionField: snapshot.documentPermissionField,
|
|
6746
|
+
stripPermissionsField: snapshot.stripPermissionsField,
|
|
6747
|
+
exposedDocPermissionKeys: snapshot.exposedDocPermissionKeys,
|
|
6748
|
+
disableFieldPermissions: snapshot.disableFieldPermissions
|
|
6749
|
+
},
|
|
6750
|
+
true
|
|
6751
|
+
),
|
|
6752
|
+
binding.scopePath ?? []
|
|
6753
|
+
);
|
|
6430
6754
|
associateDocumentAuthorization(documentAuthorization, binding, trimmed);
|
|
6431
6755
|
args.onFinalized?.(
|
|
6432
6756
|
trimmed,
|
|
@@ -6435,7 +6759,7 @@ async function finalizeSingleDoc(args, input) {
|
|
|
6435
6759
|
output: trimmed,
|
|
6436
6760
|
outputAccess: args.outputAccess,
|
|
6437
6761
|
authorization: plan.authorization,
|
|
6438
|
-
stage:
|
|
6762
|
+
stage: readDocumentAuthorizationAccess(documentAuthorization, binding).stage
|
|
6439
6763
|
})
|
|
6440
6764
|
);
|
|
6441
6765
|
}
|
|
@@ -6456,7 +6780,7 @@ async function finalizeModelOutput(args) {
|
|
|
6456
6780
|
sharedGate: gate,
|
|
6457
6781
|
resolvedLimit: limit
|
|
6458
6782
|
};
|
|
6459
|
-
return finalizeSingleDoc(internal, args.input);
|
|
6783
|
+
return finalizeSingleDoc(internal, args.input, prepareFinalizer(internal));
|
|
6460
6784
|
}
|
|
6461
6785
|
async function finalizeModelOutputs(args) {
|
|
6462
6786
|
const gate = finalizerGate(args);
|
|
@@ -6465,22 +6789,30 @@ async function finalizeModelOutputs(args) {
|
|
|
6465
6789
|
if ("documentAuthorizationStage" in args || documentAuthorizationStages && (documentAuthorizationStages.length !== inputs.length || new Set(documentAuthorizationStages).size !== inputs.length)) {
|
|
6466
6790
|
authorizationError("list finalization requires a distinct document stage per row");
|
|
6467
6791
|
}
|
|
6792
|
+
if (!inputs.length) return [];
|
|
6793
|
+
const internal = {
|
|
6794
|
+
...rest,
|
|
6795
|
+
scopePath: [...rest.scopePath ?? rest.plan.scopePath ?? []],
|
|
6796
|
+
sharedGate: gate,
|
|
6797
|
+
resolvedLimit: limit
|
|
6798
|
+
};
|
|
6799
|
+
const prepared = prepareFinalizer(internal, inputs.length > 1);
|
|
6468
6800
|
return mapWithConcurrencyLimit(inputs, limit, (input, index) => {
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6801
|
+
return finalizeSingleDoc(
|
|
6802
|
+
{
|
|
6803
|
+
...internal,
|
|
6804
|
+
onFinalized: rest.onFinalized ? (output, context) => rest.onFinalized(output, context, index) : void 0,
|
|
6805
|
+
documentAuthorizationStage: documentAuthorizationStages?.[index]
|
|
6806
|
+
},
|
|
6807
|
+
input,
|
|
6808
|
+
prepared
|
|
6809
|
+
);
|
|
6478
6810
|
});
|
|
6479
6811
|
}
|
|
6480
|
-
var
|
|
6812
|
+
var import_utils29, isVirtualContainerValue3, getScopeVirtualsObject2, getScopeVirtualNames, getScopedPermissionSchema2, resolveGlobalPermissions, resolveDocPermissions, isAbsentDependency, __finalizeInternals;
|
|
6481
6813
|
var init_finalize_model_output = __esm({
|
|
6482
6814
|
"src/output/finalize-model-output.ts"() {
|
|
6483
|
-
|
|
6815
|
+
import_utils29 = require("@web-ts-toolkit/utils");
|
|
6484
6816
|
init_document();
|
|
6485
6817
|
init_concurrency();
|
|
6486
6818
|
init_request_work();
|
|
@@ -6493,20 +6825,20 @@ var init_finalize_model_output = __esm({
|
|
|
6493
6825
|
init_field_catalog();
|
|
6494
6826
|
init_virtual_populate_execution();
|
|
6495
6827
|
init_include_output();
|
|
6496
|
-
isVirtualContainerValue3 = (value) => (0,
|
|
6828
|
+
isVirtualContainerValue3 = (value) => (0, import_utils29.isPlainObject)(value) && "sub" in value;
|
|
6497
6829
|
getScopeVirtualsObject2 = (rootVirtuals, scopePath) => {
|
|
6498
|
-
if (!rootVirtuals || !(0,
|
|
6830
|
+
if (!rootVirtuals || !(0, import_utils29.isPlainObject)(rootVirtuals)) return null;
|
|
6499
6831
|
if (scopePath.length === 0) return rootVirtuals;
|
|
6500
6832
|
let current = rootVirtuals;
|
|
6501
6833
|
for (let i = 0; i < scopePath.length; i += 2) {
|
|
6502
6834
|
const field = scopePath[i];
|
|
6503
6835
|
const subMarker = scopePath[i + 1];
|
|
6504
6836
|
if (!field || subMarker !== "sub") return null;
|
|
6505
|
-
if (!(0,
|
|
6837
|
+
if (!(0, import_utils29.isPlainObject)(current)) return null;
|
|
6506
6838
|
const container = current[field];
|
|
6507
6839
|
if (!isVirtualContainerValue3(container)) return null;
|
|
6508
6840
|
current = container.sub;
|
|
6509
|
-
if (!(0,
|
|
6841
|
+
if (!(0, import_utils29.isPlainObject)(current)) return null;
|
|
6510
6842
|
}
|
|
6511
6843
|
return current;
|
|
6512
6844
|
};
|
|
@@ -6519,11 +6851,11 @@ var init_finalize_model_output = __esm({
|
|
|
6519
6851
|
return Object.entries(scopeVirtuals).filter(([, v]) => v !== void 0 && !isVirtualContainerValue3(v)).map(([k]) => k);
|
|
6520
6852
|
};
|
|
6521
6853
|
getScopedPermissionSchema2 = (root, scopePath) => {
|
|
6522
|
-
if (!root || !(0,
|
|
6854
|
+
if (!root || !(0, import_utils29.isPlainObject)(root)) return null;
|
|
6523
6855
|
if (scopePath.length === 0) return root;
|
|
6524
6856
|
try {
|
|
6525
|
-
const scoped = (0,
|
|
6526
|
-
return (0,
|
|
6857
|
+
const scoped = (0, import_utils29.get)(root, scopePath.join("."));
|
|
6858
|
+
return (0, import_utils29.isPlainObject)(scoped) ? scoped : null;
|
|
6527
6859
|
} catch {
|
|
6528
6860
|
return null;
|
|
6529
6861
|
}
|
|
@@ -6544,7 +6876,7 @@ var init_finalize_model_output = __esm({
|
|
|
6544
6876
|
};
|
|
6545
6877
|
resolveDocPermissions = async (args, isolatedForHook, scopeContext) => {
|
|
6546
6878
|
if (args.docPermissions != null && typeof args.docPermissions === "object" && !Array.isArray(args.docPermissions)) {
|
|
6547
|
-
const grants = args.docPermissions;
|
|
6879
|
+
const grants = deepIsolateValue(args.docPermissions);
|
|
6548
6880
|
scopeContext.docPermissions = grants;
|
|
6549
6881
|
return grants;
|
|
6550
6882
|
}
|
|
@@ -6582,7 +6914,7 @@ var init_finalize_model_output = __esm({
|
|
|
6582
6914
|
const grants = await args.sharedGate.run(
|
|
6583
6915
|
() => hook.call(args.request, isolatedForHook, globalPerms, scopeContext)
|
|
6584
6916
|
);
|
|
6585
|
-
const normalized = (0,
|
|
6917
|
+
const normalized = (0, import_utils29.isPlainObject)(grants) ? grants : {};
|
|
6586
6918
|
scopeContext.docPermissions = normalized;
|
|
6587
6919
|
return normalized;
|
|
6588
6920
|
}
|
|
@@ -6654,40 +6986,20 @@ __export(index_exports, {
|
|
|
6654
6986
|
setModelOptions: () => setModelOptions
|
|
6655
6987
|
});
|
|
6656
6988
|
module.exports = __toCommonJS(index_exports);
|
|
6657
|
-
var
|
|
6989
|
+
var import_utils47 = require("@web-ts-toolkit/utils");
|
|
6658
6990
|
|
|
6659
6991
|
// src/middleware.ts
|
|
6660
6992
|
var import_express_json_router5 = __toESM(require("@web-ts-toolkit/express-json-router"));
|
|
6661
|
-
var
|
|
6993
|
+
var import_utils40 = require("@web-ts-toolkit/utils");
|
|
6662
6994
|
|
|
6663
6995
|
// src/core.ts
|
|
6664
6996
|
init_public_admission();
|
|
6665
|
-
var
|
|
6997
|
+
var import_utils39 = require("@web-ts-toolkit/utils");
|
|
6666
6998
|
init_options();
|
|
6667
|
-
|
|
6668
|
-
// src/meta.ts
|
|
6669
|
-
init_runtime();
|
|
6670
|
-
init_runtime_context();
|
|
6671
|
-
var getRuntime5 = () => getActiveRuntime() ?? defaultRuntime;
|
|
6672
|
-
var getModelRef = (modelName, refPath) => {
|
|
6673
|
-
const direct = getRuntime5().getModelRef(modelName, refPath);
|
|
6674
|
-
if (direct) return direct;
|
|
6675
|
-
if (!refPath.includes(".")) return null;
|
|
6676
|
-
try {
|
|
6677
|
-
const runtime = getRuntime5();
|
|
6678
|
-
const instance = runtime.getModelInstance?.(
|
|
6679
|
-
modelName
|
|
6680
|
-
);
|
|
6681
|
-
const schemaPath = instance?.schema?.path?.(refPath);
|
|
6682
|
-
const ref = schemaPath?.options?.ref ?? schemaPath?.caster?.options?.ref ?? null;
|
|
6683
|
-
return typeof ref === "string" && ref.length > 0 ? ref : null;
|
|
6684
|
-
} catch {
|
|
6685
|
-
return null;
|
|
6686
|
-
}
|
|
6687
|
-
};
|
|
6999
|
+
init_permission();
|
|
6688
7000
|
|
|
6689
7001
|
// src/services/base.ts
|
|
6690
|
-
var
|
|
7002
|
+
var import_utils24 = require("@web-ts-toolkit/utils");
|
|
6691
7003
|
init_options();
|
|
6692
7004
|
init_helpers();
|
|
6693
7005
|
init_document();
|
|
@@ -6813,7 +7125,7 @@ function requestFieldScope(options) {
|
|
|
6813
7125
|
init_public_admission();
|
|
6814
7126
|
|
|
6815
7127
|
// src/correlated-includes.ts
|
|
6816
|
-
var
|
|
7128
|
+
var import_utils20 = require("@web-ts-toolkit/utils");
|
|
6817
7129
|
init_request_complexity();
|
|
6818
7130
|
init_sort_policy();
|
|
6819
7131
|
var PARENT_MARKER_KEY = "$parent";
|
|
@@ -6826,10 +7138,10 @@ var FIELD_SEGMENT_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
|
6826
7138
|
var ARRAY_INDEX_SEGMENT_PATTERN = /^(0|[1-9]\d*)$/;
|
|
6827
7139
|
var ownKeys = (value) => Object.keys(value);
|
|
6828
7140
|
function isParentRefMarker(value) {
|
|
6829
|
-
return (0,
|
|
7141
|
+
return (0, import_utils20.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === PARENT_MARKER_KEY;
|
|
6830
7142
|
}
|
|
6831
7143
|
function isEscapedParentRef(value) {
|
|
6832
|
-
return (0,
|
|
7144
|
+
return (0, import_utils20.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === ESCAPE_WRAPPER_KEY;
|
|
6833
7145
|
}
|
|
6834
7146
|
function hasMarkerKey(value) {
|
|
6835
7147
|
return ownKeys(value).includes(PARENT_MARKER_KEY) || ownKeys(value).includes(ESCAPE_WRAPPER_KEY);
|
|
@@ -6848,12 +7160,12 @@ function containsParentMarkerShape(value) {
|
|
|
6848
7160
|
const seen = /* @__PURE__ */ new Set();
|
|
6849
7161
|
const visit = (current) => {
|
|
6850
7162
|
if (isParentRefMarker(current) || isEscapedParentRef(current)) return true;
|
|
6851
|
-
if ((0,
|
|
7163
|
+
if ((0, import_utils20.isArray)(current)) {
|
|
6852
7164
|
if (seen.has(current)) return false;
|
|
6853
7165
|
seen.add(current);
|
|
6854
7166
|
return current.some(visit);
|
|
6855
7167
|
}
|
|
6856
|
-
if ((0,
|
|
7168
|
+
if ((0, import_utils20.isPlainObject)(current)) {
|
|
6857
7169
|
if (seen.has(current)) return false;
|
|
6858
7170
|
seen.add(current);
|
|
6859
7171
|
if (hasMarkerKey(current)) return true;
|
|
@@ -6883,7 +7195,7 @@ function scanTemplateValueNode(value, path, issues) {
|
|
|
6883
7195
|
}
|
|
6884
7196
|
return;
|
|
6885
7197
|
}
|
|
6886
|
-
if ((0,
|
|
7198
|
+
if ((0, import_utils20.isPlainObject)(value)) {
|
|
6887
7199
|
if (hasMarkerKey(value)) {
|
|
6888
7200
|
issues.push({
|
|
6889
7201
|
message: 'Malformed $parent reference: objects carrying $parent must be exactly { "$parent": "<field>" }',
|
|
@@ -6894,7 +7206,7 @@ function scanTemplateValueNode(value, path, issues) {
|
|
|
6894
7206
|
scanTemplateObjectEntries(value, path, issues);
|
|
6895
7207
|
return;
|
|
6896
7208
|
}
|
|
6897
|
-
if ((0,
|
|
7209
|
+
if ((0, import_utils20.isArray)(value)) {
|
|
6898
7210
|
value.forEach((item, index) => scanTemplateValueNode(item, [...path, index], issues));
|
|
6899
7211
|
}
|
|
6900
7212
|
}
|
|
@@ -6935,7 +7247,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
|
|
|
6935
7247
|
continue;
|
|
6936
7248
|
}
|
|
6937
7249
|
if (LOGICAL_CLAUSE_KEYS.has(key)) {
|
|
6938
|
-
if (!(0,
|
|
7250
|
+
if (!(0, import_utils20.isArray)(child)) {
|
|
6939
7251
|
scanTemplateValueNode(child, childPath, issues);
|
|
6940
7252
|
continue;
|
|
6941
7253
|
}
|
|
@@ -6948,7 +7260,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
|
|
|
6948
7260
|
});
|
|
6949
7261
|
return;
|
|
6950
7262
|
}
|
|
6951
|
-
if ((0,
|
|
7263
|
+
if ((0, import_utils20.isPlainObject)(clause)) {
|
|
6952
7264
|
scanTemplateObjectEntries(clause, clausePath, issues);
|
|
6953
7265
|
}
|
|
6954
7266
|
});
|
|
@@ -6959,7 +7271,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
|
|
|
6959
7271
|
}
|
|
6960
7272
|
function validateCorrelatedFilterTemplate(filter2) {
|
|
6961
7273
|
const issues = [];
|
|
6962
|
-
if (!(0,
|
|
7274
|
+
if (!(0, import_utils20.isPlainObject)(filter2)) {
|
|
6963
7275
|
issues.push({ message: "Correlated include filter must be an object", path: [] });
|
|
6964
7276
|
return issues;
|
|
6965
7277
|
}
|
|
@@ -7002,13 +7314,13 @@ function collectFilterReferencePaths(filter2) {
|
|
|
7002
7314
|
return;
|
|
7003
7315
|
}
|
|
7004
7316
|
if (isEscapedParentRef(value)) return;
|
|
7005
|
-
if ((0,
|
|
7317
|
+
if ((0, import_utils20.isArray)(value)) {
|
|
7006
7318
|
if (seen.has(value)) return;
|
|
7007
7319
|
seen.add(value);
|
|
7008
7320
|
value.forEach(visitValue);
|
|
7009
7321
|
return;
|
|
7010
7322
|
}
|
|
7011
|
-
if ((0,
|
|
7323
|
+
if ((0, import_utils20.isPlainObject)(value)) {
|
|
7012
7324
|
if (seen.has(value)) return;
|
|
7013
7325
|
seen.add(value);
|
|
7014
7326
|
for (const [key, child] of Object.entries(value)) {
|
|
@@ -7054,7 +7366,7 @@ function getOwnPathValue(parent, path) {
|
|
|
7054
7366
|
return current;
|
|
7055
7367
|
}
|
|
7056
7368
|
function cloneSubstitutedValue(value) {
|
|
7057
|
-
if ((0,
|
|
7369
|
+
if ((0, import_utils20.isPlainObject)(value) || (0, import_utils20.isArray)(value)) return (0, import_utils20.cloneDeep)(value);
|
|
7058
7370
|
return value;
|
|
7059
7371
|
}
|
|
7060
7372
|
function literalParentRefObject(path) {
|
|
@@ -7095,7 +7407,7 @@ function resolveObjectEntries(obj, parent) {
|
|
|
7095
7407
|
continue;
|
|
7096
7408
|
}
|
|
7097
7409
|
if (LOGICAL_CLAUSE_KEYS.has(key)) {
|
|
7098
|
-
if (!(0,
|
|
7410
|
+
if (!(0, import_utils20.isArray)(child)) {
|
|
7099
7411
|
out[key] = resolveValueNode(child, parent, false);
|
|
7100
7412
|
continue;
|
|
7101
7413
|
}
|
|
@@ -7103,7 +7415,7 @@ function resolveObjectEntries(obj, parent) {
|
|
|
7103
7415
|
if (isParentRefMarker(clause) || isEscapedParentRef(clause)) {
|
|
7104
7416
|
throw new CorrelatedReferenceError(`Unsupported $parent reference as a direct ${key} clause`);
|
|
7105
7417
|
}
|
|
7106
|
-
if (!(0,
|
|
7418
|
+
if (!(0, import_utils20.isPlainObject)(clause)) return cloneSubstitutedValue(clause);
|
|
7107
7419
|
return resolveObjectEntries(clause, parent);
|
|
7108
7420
|
});
|
|
7109
7421
|
continue;
|
|
@@ -7132,10 +7444,10 @@ function resolveValueNode(template, parent, bare) {
|
|
|
7132
7444
|
}
|
|
7133
7445
|
const value = getOwnPathValue(parent, path);
|
|
7134
7446
|
if (value === void 0 || value === null) throw UNRESOLVABLE;
|
|
7135
|
-
if (bare && (0,
|
|
7447
|
+
if (bare && (0, import_utils20.isPlainObject)(value)) return { $eq: (0, import_utils20.cloneDeep)(value) };
|
|
7136
7448
|
return cloneSubstitutedValue(value);
|
|
7137
7449
|
}
|
|
7138
|
-
if ((0,
|
|
7450
|
+
if ((0, import_utils20.isPlainObject)(template)) {
|
|
7139
7451
|
if (hasMarkerKey(template)) {
|
|
7140
7452
|
throw new CorrelatedReferenceError(
|
|
7141
7453
|
'Malformed $parent reference: objects carrying $parent must be exactly { "$parent": "<field>" }'
|
|
@@ -7143,7 +7455,7 @@ function resolveValueNode(template, parent, bare) {
|
|
|
7143
7455
|
}
|
|
7144
7456
|
return resolveObjectEntries(template, parent);
|
|
7145
7457
|
}
|
|
7146
|
-
if ((0,
|
|
7458
|
+
if ((0, import_utils20.isArray)(template)) {
|
|
7147
7459
|
return template.map((item) => resolveValueNode(item, parent, false));
|
|
7148
7460
|
}
|
|
7149
7461
|
return template;
|
|
@@ -7177,7 +7489,7 @@ function resolveCorrelatedIdTemplate(id, parent) {
|
|
|
7177
7489
|
}
|
|
7178
7490
|
function resolveCorrelatedFilterTemplate(filter2, parent) {
|
|
7179
7491
|
try {
|
|
7180
|
-
if (!(0,
|
|
7492
|
+
if (!(0, import_utils20.isPlainObject)(filter2) || isParentRefMarker(filter2) || isEscapedParentRef(filter2)) {
|
|
7181
7493
|
throw new CorrelatedReferenceError("Correlated include filter must be an object");
|
|
7182
7494
|
}
|
|
7183
7495
|
return { status: "resolved", filter: resolveObjectEntries(filter2, parent) };
|
|
@@ -7192,7 +7504,7 @@ function validateExpandedCorrelatedOperands(expanded, limits) {
|
|
|
7192
7504
|
var MAX_NESTED_INCLUDE_DEPTH = 10;
|
|
7193
7505
|
function validateCorrelatedArgsShape(args, op, depth) {
|
|
7194
7506
|
if (args === void 0) return [];
|
|
7195
|
-
if (!(0,
|
|
7507
|
+
if (!(0, import_utils20.isPlainObject)(args)) return ["Correlated include args must be an object"];
|
|
7196
7508
|
const record3 = args;
|
|
7197
7509
|
const allowed = op === "list" ? /* @__PURE__ */ new Set(["select", "sort", "skip", "limit", "page", "pageSize", "include"]) : /* @__PURE__ */ new Set(["select", "sort", "include"]);
|
|
7198
7510
|
for (const key of Object.keys(record3)) {
|
|
@@ -7214,7 +7526,7 @@ function validateCorrelatedArgsShape(args, op, depth) {
|
|
|
7214
7526
|
return [];
|
|
7215
7527
|
}
|
|
7216
7528
|
function validateCorrelatedIncludeShape(entry, depth = 0) {
|
|
7217
|
-
if (!(0,
|
|
7529
|
+
if (!(0, import_utils20.isPlainObject)(entry)) return ["Correlated include must be an object"];
|
|
7218
7530
|
const record3 = entry;
|
|
7219
7531
|
if (record3.mode !== "correlated") return ['Correlated include mode must be "correlated"'];
|
|
7220
7532
|
if (typeof record3.model !== "string" || record3.model.length === 0)
|
|
@@ -7227,7 +7539,7 @@ function validateCorrelatedIncludeShape(entry, depth = 0) {
|
|
|
7227
7539
|
if ("localField" in record3 || "foreignField" in record3) {
|
|
7228
7540
|
return ["Correlated includes must not carry localField or foreignField"];
|
|
7229
7541
|
}
|
|
7230
|
-
if (record3.options !== void 0 && !((0,
|
|
7542
|
+
if (record3.options !== void 0 && !((0, import_utils20.isPlainObject)(record3.options) && Object.keys(record3.options).length === 0)) {
|
|
7231
7543
|
return ["Correlated include options must be absent or empty"];
|
|
7232
7544
|
}
|
|
7233
7545
|
const hasId = record3.id !== void 0;
|
|
@@ -7249,7 +7561,7 @@ function validateCorrelatedIncludeShape(entry, depth = 0) {
|
|
|
7249
7561
|
return validateCorrelatedArgsShape(record3.args, record3.op, depth);
|
|
7250
7562
|
}
|
|
7251
7563
|
function isCorrelatedInclude(value) {
|
|
7252
|
-
return (0,
|
|
7564
|
+
return (0, import_utils20.isPlainObject)(value) && value.mode === "correlated";
|
|
7253
7565
|
}
|
|
7254
7566
|
|
|
7255
7567
|
// src/services/base.ts
|
|
@@ -7473,9 +7785,31 @@ function castCountGroups(input, values) {
|
|
|
7473
7785
|
// src/services/base.ts
|
|
7474
7786
|
init_service_authorization();
|
|
7475
7787
|
|
|
7788
|
+
// src/meta.ts
|
|
7789
|
+
init_runtime();
|
|
7790
|
+
init_runtime_context();
|
|
7791
|
+
var getRuntime5 = () => getActiveRuntime() ?? defaultRuntime;
|
|
7792
|
+
var getModelRef = (modelName, refPath, runtime = getRuntime5()) => {
|
|
7793
|
+
const direct = runtime.getModelRef(modelName, refPath);
|
|
7794
|
+
if (direct) return direct;
|
|
7795
|
+
if (!refPath.includes(".")) return null;
|
|
7796
|
+
try {
|
|
7797
|
+
const instance = runtime.getModelInstance?.(
|
|
7798
|
+
modelName
|
|
7799
|
+
);
|
|
7800
|
+
const schemaPath = instance?.schema?.path?.(refPath);
|
|
7801
|
+
const element = schemaPath?.$embeddedSchemaType ?? schemaPath?.embeddedSchemaType ?? schemaPath?.caster;
|
|
7802
|
+
const ref = schemaPath?.options?.ref ?? element?.options?.ref ?? null;
|
|
7803
|
+
return typeof ref === "string" && ref.length > 0 ? ref : null;
|
|
7804
|
+
} catch {
|
|
7805
|
+
return null;
|
|
7806
|
+
}
|
|
7807
|
+
};
|
|
7808
|
+
|
|
7476
7809
|
// src/acl/related-execution.ts
|
|
7477
7810
|
init_public_admission();
|
|
7478
7811
|
init_model_output_planning();
|
|
7812
|
+
init_populate_target_configuration();
|
|
7479
7813
|
init_authorization_snapshot();
|
|
7480
7814
|
|
|
7481
7815
|
// src/acl/service-execution.ts
|
|
@@ -7513,9 +7847,9 @@ function createServiceExecution(receiver, access, authorization, applicability =
|
|
|
7513
7847
|
receiver,
|
|
7514
7848
|
binding,
|
|
7515
7849
|
authorization: call,
|
|
7516
|
-
access:
|
|
7850
|
+
access: readServiceAuthorizationAccess(call, binding),
|
|
7517
7851
|
family: execution,
|
|
7518
|
-
hydration: resolveHydration(
|
|
7852
|
+
hydration: resolveHydration(readServiceAuthorizationHydration(call, binding), hydration)
|
|
7519
7853
|
})
|
|
7520
7854
|
);
|
|
7521
7855
|
return execution;
|
|
@@ -7526,7 +7860,7 @@ function resolveHydration(configuration, source) {
|
|
|
7526
7860
|
}
|
|
7527
7861
|
function withExecutionHydration(receiver, parent, source) {
|
|
7528
7862
|
const record3 = readServiceExecution(receiver, parent);
|
|
7529
|
-
const
|
|
7863
|
+
const configuration = readServiceAuthorizationHydration(record3.authorization, record3.binding);
|
|
7530
7864
|
const execution = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
7531
7865
|
executions.set(execution, Object.freeze({ ...record3, hydration: resolveHydration(configuration, source) }));
|
|
7532
7866
|
return execution;
|
|
@@ -7563,7 +7897,7 @@ function deriveServiceExecution(receiver, parent, access, applicability = "servi
|
|
|
7563
7897
|
const execution = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
7564
7898
|
executions.set(
|
|
7565
7899
|
execution,
|
|
7566
|
-
Object.freeze({ ...record3, authorization: call, access:
|
|
7900
|
+
Object.freeze({ ...record3, authorization: call, access: readServiceAuthorizationAccess(call, record3.binding) })
|
|
7567
7901
|
);
|
|
7568
7902
|
return execution;
|
|
7569
7903
|
}
|
|
@@ -7770,16 +8104,15 @@ function captureRelatedTargets(runtime, modelName, args = {}, depth = 0, globalO
|
|
|
7770
8104
|
for (const entry of entries(args.populate)) {
|
|
7771
8105
|
const path = typeof entry === "string" ? entry : entry.path;
|
|
7772
8106
|
if (typeof entry !== "string") assertPopulateAccess(entry.access);
|
|
7773
|
-
const model = getModelRef(modelName, path);
|
|
7774
|
-
if (model
|
|
8107
|
+
const model = getModelRef(modelName, path, runtime);
|
|
8108
|
+
if (model) {
|
|
8109
|
+
const target = capturePopulateTargetConfiguration(runtime, model, `${modelName}.${path}`);
|
|
7775
8110
|
targets.push({
|
|
7776
8111
|
path,
|
|
7777
8112
|
modelName: model,
|
|
7778
|
-
configuration: captureModelAuthorizationConfiguration(runtime, model,
|
|
8113
|
+
configuration: captureModelAuthorizationConfiguration(runtime, model, target.options, globalOptions),
|
|
7779
8114
|
staticObjectIdReference: staticObjectIdReference(runtime, modelName, path, model)
|
|
7780
8115
|
});
|
|
7781
|
-
else if (model && !(globalOptions.requireRegisteredPopulateModels === void 0 ? true : globalOptions.requireRegisteredPopulateModels)) {
|
|
7782
|
-
targets.push({ path, modelName: model, kind: "passthrough", configuration: { catalog: { paths: [] } } });
|
|
7783
8116
|
}
|
|
7784
8117
|
}
|
|
7785
8118
|
for (const entry of entries(args.include)) {
|
|
@@ -7965,20 +8298,20 @@ var copyAuthorizedOutput = (value) => {
|
|
|
7965
8298
|
transferDocumentAuthorizationGraph(value, copy);
|
|
7966
8299
|
return copy;
|
|
7967
8300
|
};
|
|
7968
|
-
var isVirtualContainerValueForGuard = (value) => (0,
|
|
8301
|
+
var isVirtualContainerValueForGuard = (value) => (0, import_utils24.isPlainObject)(value) && "sub" in value;
|
|
7969
8302
|
var getScopeVirtualsForGuard = (rootVirtuals, scopePath) => {
|
|
7970
|
-
if (!rootVirtuals || !(0,
|
|
8303
|
+
if (!rootVirtuals || !(0, import_utils24.isPlainObject)(rootVirtuals)) return null;
|
|
7971
8304
|
if (scopePath.length === 0) return rootVirtuals;
|
|
7972
8305
|
let current = rootVirtuals;
|
|
7973
8306
|
for (let i = 0; i < scopePath.length; i += 2) {
|
|
7974
8307
|
const field = scopePath[i];
|
|
7975
8308
|
const subMarker = scopePath[i + 1];
|
|
7976
8309
|
if (!field || subMarker !== "sub") return null;
|
|
7977
|
-
if (!(0,
|
|
8310
|
+
if (!(0, import_utils24.isPlainObject)(current)) return null;
|
|
7978
8311
|
const container = current[field];
|
|
7979
8312
|
if (!isVirtualContainerValueForGuard(container)) return null;
|
|
7980
8313
|
current = container.sub;
|
|
7981
|
-
if (!(0,
|
|
8314
|
+
if (!(0, import_utils24.isPlainObject)(current)) return null;
|
|
7982
8315
|
}
|
|
7983
8316
|
return current;
|
|
7984
8317
|
};
|
|
@@ -8044,7 +8377,7 @@ var sanitizeSubScopeVirtualKeys = (data, snapshot, sub) => {
|
|
|
8044
8377
|
for (const entry of value) stripScope(entry, currentScope);
|
|
8045
8378
|
return;
|
|
8046
8379
|
}
|
|
8047
|
-
if (!(0,
|
|
8380
|
+
if (!(0, import_utils24.isPlainObject)(value)) return;
|
|
8048
8381
|
const record3 = value;
|
|
8049
8382
|
const leaves = getScopeVirtualLeafNames(snapshot, currentScope);
|
|
8050
8383
|
for (const leaf of leaves) {
|
|
@@ -8057,7 +8390,7 @@ var sanitizeSubScopeVirtualKeys = (data, snapshot, sub) => {
|
|
|
8057
8390
|
for (const key of Object.keys(record3)) {
|
|
8058
8391
|
if (leaves.has(key) || containers.has(key)) continue;
|
|
8059
8392
|
const child = record3[key];
|
|
8060
|
-
if (Array.isArray(child) || (0,
|
|
8393
|
+
if (Array.isArray(child) || (0, import_utils24.isPlainObject)(child)) {
|
|
8061
8394
|
stripScope(child, currentScope);
|
|
8062
8395
|
}
|
|
8063
8396
|
}
|
|
@@ -8069,7 +8402,7 @@ var LOGICAL_FILTER_KEYS = /* @__PURE__ */ new Set(["$and", "$or", "$nor"]);
|
|
|
8069
8402
|
var isOperatorKey = (key) => key.startsWith("$");
|
|
8070
8403
|
var REMOVED_VIRTUAL_FILTER = /* @__PURE__ */ Symbol("removed virtual filter clause");
|
|
8071
8404
|
var rewriteFilterObject = (value, visit) => {
|
|
8072
|
-
if (!(0,
|
|
8405
|
+
if (!(0, import_utils24.isPlainObject)(value)) return value;
|
|
8073
8406
|
let changed = false;
|
|
8074
8407
|
const entries = [];
|
|
8075
8408
|
for (const [key, child] of Object.entries(value)) {
|
|
@@ -8100,7 +8433,7 @@ var resolveVirtualFilterField = (path, scope2) => {
|
|
|
8100
8433
|
if (!Object.hasOwn(scope2, segment) || scope2[segment] === void 0) return null;
|
|
8101
8434
|
const definition = scope2[segment];
|
|
8102
8435
|
if (!isVirtualContainerValueForGuard(definition)) return REMOVED_VIRTUAL_FILTER;
|
|
8103
|
-
scope2 = (0,
|
|
8436
|
+
scope2 = (0, import_utils24.isPlainObject)(definition.sub) ? definition.sub : null;
|
|
8104
8437
|
inContainer = true;
|
|
8105
8438
|
}
|
|
8106
8439
|
return scope2;
|
|
@@ -8112,7 +8445,7 @@ var stripVirtualFilterOperator = (key, value, scope2) => {
|
|
|
8112
8445
|
}
|
|
8113
8446
|
if (key === "$all") {
|
|
8114
8447
|
return rewriteFilterClauses(value, (entry) => {
|
|
8115
|
-
if (!(0,
|
|
8448
|
+
if (!(0, import_utils24.isPlainObject)(entry) || Object.keys(entry).length !== 1 || !Object.hasOwn(entry, "$elemMatch")) return entry;
|
|
8116
8449
|
return rewriteFilterObject(entry, (operator, operand) => stripVirtualFilterOperator(operator, operand, scope2));
|
|
8117
8450
|
});
|
|
8118
8451
|
}
|
|
@@ -8127,7 +8460,7 @@ var stripVirtualFilterQuery = (value, scope2, element = false) => {
|
|
|
8127
8460
|
if (isOperatorKey(key)) return element ? stripVirtualFilterOperator(key, child, scope2) : child;
|
|
8128
8461
|
const fieldScope = resolveVirtualFilterField(key, scope2);
|
|
8129
8462
|
if (fieldScope === REMOVED_VIRTUAL_FILTER) return REMOVED_VIRTUAL_FILTER;
|
|
8130
|
-
if (!fieldScope || !(0,
|
|
8463
|
+
if (!fieldScope || !(0, import_utils24.isPlainObject)(child)) return child;
|
|
8131
8464
|
if (Object.keys(child).some(isOperatorKey)) {
|
|
8132
8465
|
return rewriteFilterObject(
|
|
8133
8466
|
child,
|
|
@@ -8149,9 +8482,9 @@ var stripSubVirtualKeysFromFilter = (filter2, snapshot, sub) => {
|
|
|
8149
8482
|
function getCorrelatedTemplateDepth(includes) {
|
|
8150
8483
|
let max = 0;
|
|
8151
8484
|
const visit = (entries, depth) => {
|
|
8152
|
-
const list = (0,
|
|
8485
|
+
const list = (0, import_utils24.castArray)(entries).filter(Boolean);
|
|
8153
8486
|
for (const entry of list) {
|
|
8154
|
-
if (!(0,
|
|
8487
|
+
if (!(0, import_utils24.isPlainObject)(entry)) continue;
|
|
8155
8488
|
max = Math.max(max, depth);
|
|
8156
8489
|
const nested = entry.args?.include;
|
|
8157
8490
|
if (nested !== void 0) {
|
|
@@ -8176,11 +8509,11 @@ function validateClientFilter(filter2) {
|
|
|
8176
8509
|
}
|
|
8177
8510
|
const blockedOperators = /* @__PURE__ */ new Set(["$where", "$expr", "$function", "$accumulator"]);
|
|
8178
8511
|
const visit = (value, path) => {
|
|
8179
|
-
if ((0,
|
|
8512
|
+
if ((0, import_utils24.isArray)(value)) {
|
|
8180
8513
|
value.forEach((item, index) => visit(item, `${path}[${index}]`));
|
|
8181
8514
|
return;
|
|
8182
8515
|
}
|
|
8183
|
-
if (!(0,
|
|
8516
|
+
if (!(0, import_utils24.isPlainObject)(value)) return;
|
|
8184
8517
|
Object.entries(value).forEach(([key, child]) => {
|
|
8185
8518
|
const nextPath = path ? `${path}.${key}` : key;
|
|
8186
8519
|
if (blockedOperators.has(key)) {
|
|
@@ -8385,7 +8718,7 @@ var Base = class {
|
|
|
8385
8718
|
}
|
|
8386
8719
|
processInclude(include, authorization) {
|
|
8387
8720
|
assertPublicAdmission(include, "include");
|
|
8388
|
-
const items = (0,
|
|
8721
|
+
const items = (0, import_utils24.compact)((0, import_utils24.castArray)(include));
|
|
8389
8722
|
const legacy = [];
|
|
8390
8723
|
const correlated = [];
|
|
8391
8724
|
const correlatedReferenceFields = [];
|
|
@@ -8421,23 +8754,23 @@ var Base = class {
|
|
|
8421
8754
|
else this.assertIncludeOutputPaths([...legacy, ...correlated]);
|
|
8422
8755
|
let includeLocalFields = [];
|
|
8423
8756
|
let includePaths = [];
|
|
8424
|
-
(0,
|
|
8757
|
+
(0, import_utils24.forEach)(legacy, (inc) => {
|
|
8425
8758
|
includeLocalFields.push(inc.localField);
|
|
8426
8759
|
includePaths.push(inc.path);
|
|
8427
8760
|
});
|
|
8428
|
-
includeLocalFields = (0,
|
|
8429
|
-
includePaths = (0,
|
|
8761
|
+
includeLocalFields = (0, import_utils24.uniq)((0, import_utils24.compact)(includeLocalFields));
|
|
8762
|
+
includePaths = (0, import_utils24.uniq)((0, import_utils24.compact)(includePaths));
|
|
8430
8763
|
return {
|
|
8431
8764
|
includes: legacy,
|
|
8432
8765
|
correlatedIncludes: correlated,
|
|
8433
8766
|
includeLocalFields,
|
|
8434
8767
|
includePaths,
|
|
8435
|
-
correlatedReferenceFields: (0,
|
|
8768
|
+
correlatedReferenceFields: (0, import_utils24.uniq)((0, import_utils24.compact)(correlatedReferenceFields))
|
|
8436
8769
|
};
|
|
8437
8770
|
}
|
|
8438
8771
|
validateIncludeOutputPath(path, modelName, configuration) {
|
|
8439
8772
|
const permissionField = configuration ? configuration.documentPermissionField ?? "_permissions" : getModelOption(modelName, "documentPermissionField");
|
|
8440
|
-
if ((0,
|
|
8773
|
+
if ((0, import_utils24.get)((0, import_utils24.set)({}, path, true), permissionField) !== void 0 || (0, import_utils24.get)((0, import_utils24.set)({}, permissionField, true), path) !== void 0) {
|
|
8441
8774
|
this.throwClientRequestError(
|
|
8442
8775
|
"bad_request" /* BadRequest */,
|
|
8443
8776
|
`Include output path ${path} overlaps document permission field ${permissionField} on model ${modelName}`
|
|
@@ -8462,9 +8795,9 @@ var Base = class {
|
|
|
8462
8795
|
const walk = (node, prefix) => {
|
|
8463
8796
|
for (const [key, value] of Object.entries(node)) {
|
|
8464
8797
|
if (value === void 0) continue;
|
|
8465
|
-
if ((0,
|
|
8798
|
+
if ((0, import_utils24.isPlainObject)(value) && "sub" in value) {
|
|
8466
8799
|
const sub = value.sub;
|
|
8467
|
-
if ((0,
|
|
8800
|
+
if ((0, import_utils24.isPlainObject)(sub)) walk(sub, prefix ? `${prefix}.${key}` : key);
|
|
8468
8801
|
continue;
|
|
8469
8802
|
}
|
|
8470
8803
|
out.push(prefix ? `${prefix}.${key}` : key);
|
|
@@ -8517,7 +8850,7 @@ var Base = class {
|
|
|
8517
8850
|
this.throwClientRequestError("bad_request" /* BadRequest */, `Model ${modelName} not found`);
|
|
8518
8851
|
}
|
|
8519
8852
|
for (const entry of entries) {
|
|
8520
|
-
if (!(0,
|
|
8853
|
+
if (!(0, import_utils24.isPlainObject)(entry)) continue;
|
|
8521
8854
|
const models = visited.get(entry) ?? /* @__PURE__ */ new Set();
|
|
8522
8855
|
if (models.has(modelName)) continue;
|
|
8523
8856
|
models.add(modelName);
|
|
@@ -8530,7 +8863,7 @@ var Base = class {
|
|
|
8530
8863
|
const target = targets?.find((target2) => target2.path === entry.path);
|
|
8531
8864
|
if (nested)
|
|
8532
8865
|
pending.push({
|
|
8533
|
-
entries: (0,
|
|
8866
|
+
entries: (0, import_utils24.compact)((0, import_utils24.castArray)(nested)),
|
|
8534
8867
|
modelName: entry.model,
|
|
8535
8868
|
configuration: target?.configuration,
|
|
8536
8869
|
targets: target?.relatedTargets
|
|
@@ -8540,7 +8873,7 @@ var Base = class {
|
|
|
8540
8873
|
}
|
|
8541
8874
|
}
|
|
8542
8875
|
getForeignKeyValues(value) {
|
|
8543
|
-
return (0,
|
|
8876
|
+
return (0, import_utils24.flatten)((0, import_utils24.castArray)(value));
|
|
8544
8877
|
}
|
|
8545
8878
|
getForeignKey(value) {
|
|
8546
8879
|
return String(value);
|
|
@@ -8548,7 +8881,7 @@ var Base = class {
|
|
|
8548
8881
|
buildForeignKeyIndex(rows2, foreignField) {
|
|
8549
8882
|
const index = /* @__PURE__ */ new Map();
|
|
8550
8883
|
for (const row of rows2) {
|
|
8551
|
-
for (const value of this.getForeignKeyValues((0,
|
|
8884
|
+
for (const value of this.getForeignKeyValues((0, import_utils24.get)(row, foreignField))) {
|
|
8552
8885
|
const key = this.getForeignKey(value);
|
|
8553
8886
|
const values = index.get(key);
|
|
8554
8887
|
if (values) values.push(row);
|
|
@@ -8584,9 +8917,9 @@ var Base = class {
|
|
|
8584
8917
|
async includeDocs(docs, include, parentAuthorization) {
|
|
8585
8918
|
assertPublicAdmission(include, "include");
|
|
8586
8919
|
if (!include) return docs;
|
|
8587
|
-
const includes = (0,
|
|
8920
|
+
const includes = (0, import_utils24.compact)((0, import_utils24.castArray)(include));
|
|
8588
8921
|
if (includes.length === 0) return docs;
|
|
8589
|
-
const isSingle = !(0,
|
|
8922
|
+
const isSingle = !(0, import_utils24.isArray)(docs);
|
|
8590
8923
|
let docList = (isSingle ? [docs] : docs).map(prepareIncludeOutput);
|
|
8591
8924
|
for (let x = 0; x < includes.length; x++) {
|
|
8592
8925
|
const include2 = includes[x];
|
|
@@ -8616,7 +8949,7 @@ var Base = class {
|
|
|
8616
8949
|
const svc = await this.getAuthorizedTargetService(model, "read", path, parentAuthorization);
|
|
8617
8950
|
for (let y = 0; y < docs.length; y++) {
|
|
8618
8951
|
const doc = docs[y];
|
|
8619
|
-
const localValue = (0,
|
|
8952
|
+
const localValue = (0, import_utils24.get)(doc, localField);
|
|
8620
8953
|
const execution = this.relatedExecution(svc, include, parentAuthorization);
|
|
8621
8954
|
const prepared = await prepareModelQuery(
|
|
8622
8955
|
svc,
|
|
@@ -8651,15 +8984,15 @@ var Base = class {
|
|
|
8651
8984
|
const { model, op, path, localField, foreignField, filter: _filters, args = {}, options = {} } = include;
|
|
8652
8985
|
const svc = await this.getAuthorizedTargetService(model, op, path, parentAuthorization);
|
|
8653
8986
|
const includeLocalValues = [];
|
|
8654
|
-
(0,
|
|
8655
|
-
includeLocalValues.push(...this.getForeignKeyValues((0,
|
|
8987
|
+
(0, import_utils24.forEach)(docs, (doc) => {
|
|
8988
|
+
includeLocalValues.push(...this.getForeignKeyValues((0, import_utils24.get)(doc, localField)));
|
|
8656
8989
|
});
|
|
8657
8990
|
const execution = this.relatedExecution(svc, include, parentAuthorization);
|
|
8658
8991
|
const prepared = await prepareModelQuery(
|
|
8659
8992
|
svc,
|
|
8660
8993
|
execution,
|
|
8661
8994
|
{ kind: "client-read", filter: _filters ?? {} },
|
|
8662
|
-
{ [foreignField]: { $in: (0,
|
|
8995
|
+
{ [foreignField]: { $in: (0, import_utils24.flatten)(includeLocalValues) } },
|
|
8663
8996
|
true
|
|
8664
8997
|
);
|
|
8665
8998
|
const trustedArgs = this.sanitizeIncludeArgs(args, "list");
|
|
@@ -8702,7 +9035,7 @@ var Base = class {
|
|
|
8702
9035
|
}
|
|
8703
9036
|
for (let y = 0; y < docs.length; y++) {
|
|
8704
9037
|
const doc = docs[y];
|
|
8705
|
-
const matches = this.getIndexedMatches(index, (0,
|
|
9038
|
+
const matches = this.getIndexedMatches(index, (0, import_utils24.get)(doc, localField));
|
|
8706
9039
|
const isolated = matches.map((m) => copyAuthorizedOutput(m));
|
|
8707
9040
|
attachIncludeOutput(doc, path, op === "list" ? isolated : isolated[0]);
|
|
8708
9041
|
}
|
|
@@ -8711,7 +9044,7 @@ var Base = class {
|
|
|
8711
9044
|
async includeDocsCount(docs, include, parentAuthorization) {
|
|
8712
9045
|
const { model, path, localField, foreignField, filter: _filters } = include;
|
|
8713
9046
|
const svc = await this.getAuthorizedTargetService(model, "count", path, parentAuthorization);
|
|
8714
|
-
const groups = prepareCountGroups(docs, (doc) => (0,
|
|
9047
|
+
const groups = prepareCountGroups(docs, (doc) => (0, import_utils24.get)(doc, localField));
|
|
8715
9048
|
const execution = this.relatedExecution(svc, include, parentAuthorization);
|
|
8716
9049
|
const prepared = await prepareModelQuery(
|
|
8717
9050
|
svc,
|
|
@@ -8765,7 +9098,7 @@ var Base = class {
|
|
|
8765
9098
|
}
|
|
8766
9099
|
const state = this.getCorrelatedExecState();
|
|
8767
9100
|
docs = docs.map(prepareIncludeOutput);
|
|
8768
|
-
const resolvedSnapshots = snapshots2 ?? docs.map((doc) => (0,
|
|
9101
|
+
const resolvedSnapshots = snapshots2 ?? docs.map((doc) => (0, import_utils24.cloneDeep)(toObject(getIncludeSource(doc))));
|
|
8769
9102
|
for (const include of correlatedIncludes) {
|
|
8770
9103
|
switch (include.op) {
|
|
8771
9104
|
case "read":
|
|
@@ -9114,10 +9447,10 @@ var Base = class {
|
|
|
9114
9447
|
}
|
|
9115
9448
|
let ret = result2.data;
|
|
9116
9449
|
if (sqOptions.path) {
|
|
9117
|
-
ret = (0,
|
|
9450
|
+
ret = (0, import_utils24.isArray)(ret) ? (0, import_utils24.flatten)(ret.map((v) => (0, import_utils24.get)(v, sqOptions.path))) : (0, import_utils24.get)(ret, sqOptions.path);
|
|
9118
9451
|
}
|
|
9119
9452
|
if (sqOptions.compact) {
|
|
9120
|
-
ret = (0,
|
|
9453
|
+
ret = (0, import_utils24.compact)((0, import_utils24.castArray)(ret));
|
|
9121
9454
|
}
|
|
9122
9455
|
return ret;
|
|
9123
9456
|
}
|
|
@@ -9129,11 +9462,11 @@ var Base = class {
|
|
|
9129
9462
|
};
|
|
9130
9463
|
|
|
9131
9464
|
// src/services/service.ts
|
|
9132
|
-
var
|
|
9465
|
+
var import_utils35 = require("@web-ts-toolkit/utils");
|
|
9133
9466
|
var import_just_diff = require("just-diff");
|
|
9134
9467
|
|
|
9135
9468
|
// src/model.ts
|
|
9136
|
-
var
|
|
9469
|
+
var import_utils25 = require("@web-ts-toolkit/utils");
|
|
9137
9470
|
init_runtime_context();
|
|
9138
9471
|
init_runtime();
|
|
9139
9472
|
function admitModelPersistence(adapter, scheduler) {
|
|
@@ -9209,7 +9542,7 @@ var Model = class {
|
|
|
9209
9542
|
}
|
|
9210
9543
|
/** Cast a copy using this model's query schema/setters, without executing query middleware or persistence. */
|
|
9211
9544
|
castFilter(filter2) {
|
|
9212
|
-
const query = this.mongooseModel.countDocuments((0,
|
|
9545
|
+
const query = this.mongooseModel.countDocuments((0, import_utils25.cloneDeep)(filter2));
|
|
9213
9546
|
return query.cast(this.mongooseModel);
|
|
9214
9547
|
}
|
|
9215
9548
|
// see https://mongoosejs.com/docs/api.html#model_Model.distinct
|
|
@@ -9223,7 +9556,7 @@ var Model = class {
|
|
|
9223
9556
|
var model_default = Model;
|
|
9224
9557
|
|
|
9225
9558
|
// src/acl/distinct-field-authorization.ts
|
|
9226
|
-
var
|
|
9559
|
+
var import_utils26 = require("@web-ts-toolkit/utils");
|
|
9227
9560
|
init_field_authorization();
|
|
9228
9561
|
init_field_catalog();
|
|
9229
9562
|
var schemaVariants = (schema) => Object.values(schema.discriminators ?? {});
|
|
@@ -9305,8 +9638,8 @@ function isDistinctFieldAuthorized(args) {
|
|
|
9305
9638
|
if (path !== field && !path.startsWith(`${field}.`) && !field.startsWith(`${path}.`)) continue;
|
|
9306
9639
|
if (path.startsWith(`${field}.`) && (!eligible(path) || !schemaShape(schema, path) || !granted(path)))
|
|
9307
9640
|
return false;
|
|
9308
|
-
if ((0,
|
|
9309
|
-
if (!(0,
|
|
9641
|
+
if ((0, import_utils26.isPlainObject)(raw) && raw.sub !== void 0) {
|
|
9642
|
+
if (!(0, import_utils26.isPlainObject)(raw.sub) || !declaredRulesSafe(raw.sub, path, next)) return false;
|
|
9310
9643
|
}
|
|
9311
9644
|
}
|
|
9312
9645
|
return true;
|
|
@@ -9483,7 +9816,7 @@ init_document();
|
|
|
9483
9816
|
init_populate_target();
|
|
9484
9817
|
|
|
9485
9818
|
// src/helpers/apply-update.ts
|
|
9486
|
-
var
|
|
9819
|
+
var import_utils30 = require("@web-ts-toolkit/utils");
|
|
9487
9820
|
init_lib();
|
|
9488
9821
|
function applyUpdate(target, data, allowedFields) {
|
|
9489
9822
|
const wholeFields = /* @__PURE__ */ new Set();
|
|
@@ -9499,17 +9832,17 @@ function applyUpdate(target, data, allowedFields) {
|
|
|
9499
9832
|
}
|
|
9500
9833
|
};
|
|
9501
9834
|
for (const field of allowedFields) {
|
|
9502
|
-
collectBoundary((0,
|
|
9835
|
+
collectBoundary((0, import_utils30.set)({}, field, true));
|
|
9503
9836
|
}
|
|
9504
9837
|
const apply = (values, prefix = "") => {
|
|
9505
9838
|
for (const [key, value] of Object.entries(values)) {
|
|
9506
9839
|
const path = prefix ? `${prefix}.${key}` : key;
|
|
9507
|
-
if (partialContainers.has(path) && !wholeFields.has(path) && ((0,
|
|
9840
|
+
if (partialContainers.has(path) && !wholeFields.has(path) && ((0, import_utils30.isPlainObject)(value) || Array.isArray(value))) {
|
|
9508
9841
|
apply(value, path);
|
|
9509
9842
|
} else if (isDocument2(target)) {
|
|
9510
9843
|
target.set(path, value);
|
|
9511
9844
|
} else {
|
|
9512
|
-
(0,
|
|
9845
|
+
(0, import_utils30.set)(target, path, value);
|
|
9513
9846
|
}
|
|
9514
9847
|
}
|
|
9515
9848
|
};
|
|
@@ -9517,7 +9850,7 @@ function applyUpdate(target, data, allowedFields) {
|
|
|
9517
9850
|
}
|
|
9518
9851
|
|
|
9519
9852
|
// src/acl/model-input-admission.ts
|
|
9520
|
-
var
|
|
9853
|
+
var import_utils32 = require("@web-ts-toolkit/utils");
|
|
9521
9854
|
var import_mongoose8 = require("mongoose");
|
|
9522
9855
|
init_document();
|
|
9523
9856
|
init_request_work();
|
|
@@ -9525,7 +9858,7 @@ init_logger_helpers();
|
|
|
9525
9858
|
init_request_complexity();
|
|
9526
9859
|
|
|
9527
9860
|
// src/acl/select-resolution.ts
|
|
9528
|
-
var
|
|
9861
|
+
var import_utils31 = require("@web-ts-toolkit/utils");
|
|
9529
9862
|
init_core_shared();
|
|
9530
9863
|
init_helpers();
|
|
9531
9864
|
async function collectAllowedFieldsForRequest({
|
|
@@ -9599,15 +9932,15 @@ async function resolveSelectForRequest({
|
|
|
9599
9932
|
const excludeall = normalizedSelect.every((v) => v.startsWith("-"));
|
|
9600
9933
|
if (excludeall) {
|
|
9601
9934
|
normalizedSelect = normalizedSelect.map((v) => v.substring(1));
|
|
9602
|
-
fields = (0,
|
|
9935
|
+
fields = (0, import_utils31.difference)(fields, normalizedSelect);
|
|
9603
9936
|
if (excludeid) fields.push("-_id");
|
|
9604
9937
|
} else {
|
|
9605
|
-
fields = (0,
|
|
9938
|
+
fields = (0, import_utils31.intersection)(normalizedSelect, fields.concat(excludeid ? "-_id" : "_id"));
|
|
9606
9939
|
}
|
|
9607
9940
|
}
|
|
9608
9941
|
return fields.concat(strippedAlways);
|
|
9609
9942
|
}
|
|
9610
|
-
return (0,
|
|
9943
|
+
return (0, import_utils31.intersection)(normalizedSelect, fields);
|
|
9611
9944
|
}
|
|
9612
9945
|
function stripVirtuals(fields, virtualNames) {
|
|
9613
9946
|
const set13 = virtualNames instanceof Set ? virtualNames : new Set(virtualNames ?? []);
|
|
@@ -9638,7 +9971,7 @@ init_field_catalog();
|
|
|
9638
9971
|
init_service_authorization();
|
|
9639
9972
|
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
9640
9973
|
var inside = (path, root) => path === root || path.startsWith(`${root}.`);
|
|
9641
|
-
var record2 = (value) => (0,
|
|
9974
|
+
var record2 = (value) => (0, import_utils32.isPlainObject)(value);
|
|
9642
9975
|
function inputValue(value) {
|
|
9643
9976
|
if (typeof value === "function" || typeof value === "symbol") {
|
|
9644
9977
|
authorizationError("input values must be persisted data, not functions or symbols");
|
|
@@ -9707,7 +10040,7 @@ function requestBoundaries(fields) {
|
|
|
9707
10040
|
else visit(value, path);
|
|
9708
10041
|
}
|
|
9709
10042
|
};
|
|
9710
|
-
for (const field of fields) visit((0,
|
|
10043
|
+
for (const field of fields) visit((0, import_utils32.set)({}, field, true));
|
|
9711
10044
|
return [...new Set(result2)];
|
|
9712
10045
|
}
|
|
9713
10046
|
function ownValue(data, parts) {
|
|
@@ -9837,7 +10170,7 @@ function admitModelInput(args) {
|
|
|
9837
10170
|
if (forbidden(catalog, path, requested)) continue;
|
|
9838
10171
|
const supplied = ownValue(data, parts);
|
|
9839
10172
|
if (!supplied) continue;
|
|
9840
|
-
(0,
|
|
10173
|
+
(0, import_utils32.set)(allowedData, field, copyInputValue(supplied.value, path, catalog, scopedRequests, logicalPath(field)));
|
|
9841
10174
|
selected.push(field);
|
|
9842
10175
|
}
|
|
9843
10176
|
return { allowedData, allowedFields };
|
|
@@ -9849,7 +10182,7 @@ async function requestInputFields(args) {
|
|
|
9849
10182
|
const prefix = configuration.modelPermissionPrefix ?? "";
|
|
9850
10183
|
return collectModelRequestFields({
|
|
9851
10184
|
req: args.binding.request,
|
|
9852
|
-
permissionSchema: args.scopePath ? (0,
|
|
10185
|
+
permissionSchema: args.scopePath ? (0, import_utils32.get)(configuration.permissionSchema, [args.scopePath, "sub"]) : configuration.permissionSchema,
|
|
9853
10186
|
access: args.access,
|
|
9854
10187
|
permissions,
|
|
9855
10188
|
grants,
|
|
@@ -9893,13 +10226,13 @@ init_logger_helpers();
|
|
|
9893
10226
|
init_lib();
|
|
9894
10227
|
|
|
9895
10228
|
// src/services/model-subdocument-service.ts
|
|
9896
|
-
var
|
|
10229
|
+
var import_utils34 = require("@web-ts-toolkit/utils");
|
|
9897
10230
|
init_helpers();
|
|
9898
10231
|
init_document();
|
|
9899
10232
|
init_public_admission();
|
|
9900
10233
|
|
|
9901
10234
|
// src/acl/subdocument-authorization.ts
|
|
9902
|
-
var
|
|
10235
|
+
var import_utils33 = require("@web-ts-toolkit/utils");
|
|
9903
10236
|
init_helpers();
|
|
9904
10237
|
init_document();
|
|
9905
10238
|
init_core_shared();
|
|
@@ -10088,8 +10421,8 @@ async function subdocumentGateAllowed(service, gate) {
|
|
|
10088
10421
|
let guard2;
|
|
10089
10422
|
if (access.startsWith("subs.")) {
|
|
10090
10423
|
const [, sub, op] = access.split(".");
|
|
10091
|
-
guard2 = (0,
|
|
10092
|
-
if (guard2 === void 0) guard2 = (0,
|
|
10424
|
+
guard2 = (0, import_utils33.get)(configuration, `operationAccess.${access}`);
|
|
10425
|
+
if (guard2 === void 0) guard2 = (0, import_utils33.get)(configuration, `operationAccess.subs.${sub}`);
|
|
10093
10426
|
if (guard2 === void 0) guard2 = getCapturedAuthorizationOption(configuration, `operationAccess.${op}`);
|
|
10094
10427
|
} else guard2 = getCapturedAuthorizationOption(configuration, `operationAccess.${access}`);
|
|
10095
10428
|
return evaluateRouteGuard(
|
|
@@ -10220,7 +10553,7 @@ async function visibleMutationRows(service, call, parentId, rows2) {
|
|
|
10220
10553
|
const read = await subdocumentRows(service, visibility.child, selected, selected, call.sub);
|
|
10221
10554
|
const list = visibility.list ? await subdocumentRows(service, visibility.list, {}, {}, call.sub) : {};
|
|
10222
10555
|
if (read === false || list === false) return [];
|
|
10223
|
-
const visible = filterCollection((0,
|
|
10556
|
+
const visible = filterCollection((0, import_utils34.get)(parent, call.sub), intersectFilters(read, list));
|
|
10224
10557
|
return await finalizeSubdocumentRows(service, call.output, parent, visible);
|
|
10225
10558
|
} catch {
|
|
10226
10559
|
return [];
|
|
@@ -10245,7 +10578,7 @@ async function listSub(service, id, sub, options) {
|
|
|
10245
10578
|
populate: []
|
|
10246
10579
|
});
|
|
10247
10580
|
if (!parent) return denied2("not_found" /* NotFound */);
|
|
10248
|
-
const rows2 = filterCollection((0,
|
|
10581
|
+
const rows2 = filterCollection((0, import_utils34.get)(parent, sub), childFilter);
|
|
10249
10582
|
const data = await finalizeSubdocumentRows(service, call.output, parent, rows2);
|
|
10250
10583
|
return { success: true, kind: "list", code: "success" /* Success */, data, count: data.length };
|
|
10251
10584
|
});
|
|
@@ -10269,7 +10602,7 @@ async function readSub(service, id, sub, subId, options) {
|
|
|
10269
10602
|
});
|
|
10270
10603
|
if (!parent) return denied2("not_found" /* NotFound */);
|
|
10271
10604
|
const row = findElement(
|
|
10272
|
-
(0,
|
|
10605
|
+
(0, import_utils34.get)(capture ? parent : copySubdocumentParent(parent), sub),
|
|
10273
10606
|
childFilter
|
|
10274
10607
|
);
|
|
10275
10608
|
if (!row) return denied2("not_found" /* NotFound */);
|
|
@@ -10290,7 +10623,7 @@ async function updateSub(service, persist, id, sub, subId, data, options) {
|
|
|
10290
10623
|
const identity = { _id: subId };
|
|
10291
10624
|
const filter2 = await subdocumentRows(service, call.child, identity, identity, sub);
|
|
10292
10625
|
if (filter2 === false) return denied2();
|
|
10293
|
-
const row = findElement((0,
|
|
10626
|
+
const row = findElement((0, import_utils34.get)(parent, sub), filter2);
|
|
10294
10627
|
if (!row) return denied2("not_found" /* NotFound */);
|
|
10295
10628
|
const original = isolateDocForOutput(row);
|
|
10296
10629
|
const admit = await inputAdmission(service, call, parent);
|
|
@@ -10317,7 +10650,7 @@ async function bulkUpdateSub(service, persist, id, sub, data, options) {
|
|
|
10317
10650
|
const selected = { _id: { $in: data.map((row) => row._id) } };
|
|
10318
10651
|
const filter2 = await subdocumentRows(service, call.child, selected, selected, sub);
|
|
10319
10652
|
if (filter2 === false) return denied2();
|
|
10320
|
-
const rows2 = filterCollection((0,
|
|
10653
|
+
const rows2 = filterCollection((0, import_utils34.get)(parent, sub), filter2);
|
|
10321
10654
|
const originals = rows2.map((row) => isolateDocForOutput(row));
|
|
10322
10655
|
const admit = await inputAdmission(service, call, parent);
|
|
10323
10656
|
for (const [index, row] of rows2.entries()) {
|
|
@@ -10346,7 +10679,7 @@ async function createSub(service, persist, id, sub, data, options) {
|
|
|
10346
10679
|
const lookup = await mutationParent(service, id, call);
|
|
10347
10680
|
if ("error" in lookup) return lookup.error;
|
|
10348
10681
|
const { parent } = lookup;
|
|
10349
|
-
const rows2 = (0,
|
|
10682
|
+
const rows2 = (0, import_utils34.get)(parent, sub);
|
|
10350
10683
|
const admit = await inputAdmission(service, call, parent);
|
|
10351
10684
|
const allowed = (Array.isArray(data) ? data : [data]).map((row) => admit(row).allowedData);
|
|
10352
10685
|
if (addFirst) rows2.unshift(...allowed);
|
|
@@ -10367,7 +10700,7 @@ async function deleteSub(service, persist, id, sub, subId, options) {
|
|
|
10367
10700
|
const identity = { _id: subId };
|
|
10368
10701
|
const filter2 = await subdocumentRows(service, call.child, identity, identity, sub);
|
|
10369
10702
|
if (filter2 === false) return denied2();
|
|
10370
|
-
const row = findElement((0,
|
|
10703
|
+
const row = findElement((0, import_utils34.get)(parent, sub), filter2);
|
|
10371
10704
|
if (!row) return denied2("not_found" /* NotFound */);
|
|
10372
10705
|
await ("deleteOne" in row ? row.deleteOne?.() : row.remove?.());
|
|
10373
10706
|
await persist(() => parent.save());
|
|
@@ -10640,7 +10973,8 @@ var Service = class extends Base {
|
|
|
10640
10973
|
async finalizeDirectOutput(args) {
|
|
10641
10974
|
const { plan, context } = args;
|
|
10642
10975
|
const { authorization, authorizationBinding: binding } = plan;
|
|
10643
|
-
const
|
|
10976
|
+
const access = readServiceAuthorizationAccess(authorization, binding);
|
|
10977
|
+
const configuration = readServiceOutputMetadata(authorization, binding);
|
|
10644
10978
|
const source = getIncludeSource(args.doc);
|
|
10645
10979
|
const snapshot = isolateDocForOutput(source);
|
|
10646
10980
|
for (const key of Object.keys(snapshot))
|
|
@@ -10681,20 +11015,20 @@ var Service = class extends Base {
|
|
|
10681
11015
|
const field = configuration.documentPermissionField ?? "_permissions";
|
|
10682
11016
|
unsetDocPath(output, field);
|
|
10683
11017
|
if (!configuration.stripPermissionsField) {
|
|
10684
|
-
(0,
|
|
11018
|
+
(0, import_utils35.set)(output, field, args.includePermissions || args.includeFieldPermissions ? deepIsolateValue(grants) : {});
|
|
10685
11019
|
if (args.includeFieldPermissions && !configuration.disableFieldPermissions) {
|
|
10686
11020
|
const rowAccess = this.asServiceHookContext(context).fieldPermissionAccess ?? await this.getFieldPermissionAccess([snapshot._id]);
|
|
10687
11021
|
const id = String(snapshot._id);
|
|
10688
11022
|
const views = rowAccess.readIds?.has(id) ? await requestOutputFieldPaths(handle, binding, "read") : [];
|
|
10689
11023
|
const edits = rowAccess.updateIds?.has(id) ? await requestOutputFieldPaths(handle, binding, "update") : [];
|
|
10690
11024
|
const map2 = (paths) => paths.length ? Object.fromEntries(paths.map((path) => [path, true])) : { $: "_" };
|
|
10691
|
-
(0,
|
|
10692
|
-
(0,
|
|
10693
|
-
} else if (!args.includePermissions) (0,
|
|
11025
|
+
(0, import_utils35.set)(output, `${field}._view`, map2(views));
|
|
11026
|
+
(0, import_utils35.set)(output, `${field}._edit`, map2(edits));
|
|
11027
|
+
} else if (!args.includePermissions) (0, import_utils35.set)(output, field, { _view: { $: "_" }, _edit: { $: "_" } });
|
|
10694
11028
|
const exposed = configuration.exposedDocPermissionKeys;
|
|
10695
11029
|
if (exposed) {
|
|
10696
|
-
const metadata = (0,
|
|
10697
|
-
(0,
|
|
11030
|
+
const metadata = (0, import_utils35.get)(output, field);
|
|
11031
|
+
(0, import_utils35.set)(
|
|
10698
11032
|
output,
|
|
10699
11033
|
field,
|
|
10700
11034
|
Object.fromEntries(
|
|
@@ -10955,7 +11289,7 @@ var Service = class extends Base {
|
|
|
10955
11289
|
return docs.map((doc) => {
|
|
10956
11290
|
try {
|
|
10957
11291
|
const plain = toObject(doc);
|
|
10958
|
-
const val = (0,
|
|
11292
|
+
const val = (0, import_utils35.get)(plain, associationField);
|
|
10959
11293
|
return deepIsolateValue(val);
|
|
10960
11294
|
} catch {
|
|
10961
11295
|
return void 0;
|
|
@@ -10994,10 +11328,6 @@ var Service = class extends Base {
|
|
|
10994
11328
|
const target = captured.relatedTargets.find((target2) => target2.path === descriptor.path);
|
|
10995
11329
|
const modelName = target?.modelName;
|
|
10996
11330
|
if (!modelName) continue;
|
|
10997
|
-
if (target.kind === "passthrough") {
|
|
10998
|
-
result2.push({ path: descriptor.path, select: descriptor.select });
|
|
10999
|
-
continue;
|
|
11000
|
-
}
|
|
11001
11331
|
const policy = relatedPolicy(state.authorization, state.binding, descriptor.path);
|
|
11002
11332
|
const svc = this.requestCore.getPublicService(modelName);
|
|
11003
11333
|
const child = createRelatedExecution(
|
|
@@ -11016,7 +11346,7 @@ var Service = class extends Base {
|
|
|
11016
11346
|
if (isExecutionRowDenied(svc, child)) continue;
|
|
11017
11347
|
const childState = readServiceExecution(svc, child);
|
|
11018
11348
|
const targetConfiguration = readServiceAuthorization(childState.authorization, childState.binding).configuration;
|
|
11019
|
-
if (policy?.operation.mode !== "grant" && !await this.hookGate.run(
|
|
11349
|
+
if (targetConfiguration.requireOperationAccessForPopulateQueries !== false && policy?.operation.mode !== "grant" && !await this.hookGate.run(
|
|
11020
11350
|
() => evaluateRouteGuard(
|
|
11021
11351
|
this.req,
|
|
11022
11352
|
getAuthorizationPermissions(childState.authorization, childState.binding),
|
|
@@ -11068,7 +11398,7 @@ var Service = class extends Base {
|
|
|
11068
11398
|
if (this.isScalarPopulateValue(rawTarget)) return rawTarget;
|
|
11069
11399
|
const isDoc = (() => {
|
|
11070
11400
|
try {
|
|
11071
|
-
if ((0,
|
|
11401
|
+
if ((0, import_utils35.isPlainObject)(rawTarget)) return true;
|
|
11072
11402
|
const maybe = rawTarget;
|
|
11073
11403
|
if (maybe && typeof maybe === "object" && "_doc" in maybe) return true;
|
|
11074
11404
|
if (maybe && typeof maybe.toObject === "function") return true;
|
|
@@ -11156,7 +11486,7 @@ var Service = class extends Base {
|
|
|
11156
11486
|
child = getDocValue(current, key);
|
|
11157
11487
|
if (child === void 0) {
|
|
11158
11488
|
try {
|
|
11159
|
-
child = (0,
|
|
11489
|
+
child = (0, import_utils35.get)(current, key);
|
|
11160
11490
|
} catch {
|
|
11161
11491
|
return;
|
|
11162
11492
|
}
|
|
@@ -11391,7 +11721,7 @@ var Service = class extends Base {
|
|
|
11391
11721
|
originalDocumentSnapshot: toObject(doc),
|
|
11392
11722
|
resolvedQuery: query
|
|
11393
11723
|
};
|
|
11394
|
-
const correlatedSnapshots = [(0,
|
|
11724
|
+
const correlatedSnapshots = [(0, import_utils35.cloneDeep)(toObject(doc))];
|
|
11395
11725
|
try {
|
|
11396
11726
|
doc = await this.includeDocs(doc, includes, state.authorization);
|
|
11397
11727
|
if (correlatedIncludes.length > 0) {
|
|
@@ -11573,7 +11903,7 @@ var Service = class extends Base {
|
|
|
11573
11903
|
const findAssociationField = this.getAssociationFieldFromOptions(options);
|
|
11574
11904
|
const withAssocSelect = findAssociationField && !finalSelect.includes(findAssociationField) ? [...finalSelect, findAssociationField] : finalSelect;
|
|
11575
11905
|
const dbSelect = this.buildDbSelectForAssociation(withAssocSelect, findAssociationField);
|
|
11576
|
-
const filteredPopulate = (0,
|
|
11906
|
+
const filteredPopulate = (0, import_utils35.isArray)(withAssocSelect) && (0, import_utils35.isArray)(_populate) ? _populate.filter(
|
|
11577
11907
|
(p) => [
|
|
11578
11908
|
...virtualPlan.publicPersistedFetchSelection,
|
|
11579
11909
|
...findAssociationField ? [findAssociationField] : []
|
|
@@ -11633,7 +11963,7 @@ var Service = class extends Base {
|
|
|
11633
11963
|
findAssociationField ? [findAssociationField] : []
|
|
11634
11964
|
);
|
|
11635
11965
|
const capturedAssociation = findAssociationField ? this.captureAssociationValues(docs, findAssociationField) : void 0;
|
|
11636
|
-
const correlatedSnapshots = docs.map((doc) => (0,
|
|
11966
|
+
const correlatedSnapshots = docs.map((doc) => (0, import_utils35.cloneDeep)(toObject(doc)));
|
|
11637
11967
|
try {
|
|
11638
11968
|
docs = await this.includeDocs(docs, includes, state.authorization);
|
|
11639
11969
|
if (correlatedIncludes.length > 0) {
|
|
@@ -11832,12 +12162,12 @@ var Service = class extends Base {
|
|
|
11832
12162
|
context.allowedFields = allowedFields;
|
|
11833
12163
|
context.allowedData = allowedData;
|
|
11834
12164
|
const validated = await this.validate(allowedData, "create", context);
|
|
11835
|
-
if ((0,
|
|
12165
|
+
if ((0, import_utils35.isBoolean)(validated)) {
|
|
11836
12166
|
if (!validated) {
|
|
11837
12167
|
validationErrors.push({ index, errors: [] });
|
|
11838
12168
|
return void 0;
|
|
11839
12169
|
}
|
|
11840
|
-
} else if ((0,
|
|
12170
|
+
} else if ((0, import_utils35.isArray)(validated)) {
|
|
11841
12171
|
if (validated.length > 0) {
|
|
11842
12172
|
validationErrors.push({
|
|
11843
12173
|
index,
|
|
@@ -12048,7 +12378,7 @@ var Service = class extends Base {
|
|
|
12048
12378
|
}
|
|
12049
12379
|
let doc = await this.model.findOne({
|
|
12050
12380
|
filter: _filter,
|
|
12051
|
-
select: (0,
|
|
12381
|
+
select: (0, import_utils35.uniq)([...updatePlan.persistedFetchSelection, ...inputFetchPaths(captured.configuration.catalog)]).map(
|
|
12052
12382
|
(path) => `+${path}`
|
|
12053
12383
|
)
|
|
12054
12384
|
});
|
|
@@ -12087,12 +12417,12 @@ var Service = class extends Base {
|
|
|
12087
12417
|
context.allowedFields = allowedFields;
|
|
12088
12418
|
context.allowedData = allowedData;
|
|
12089
12419
|
const validated = await this.validate(allowedData, "update", context);
|
|
12090
|
-
if ((0,
|
|
12420
|
+
if ((0, import_utils35.isBoolean)(validated)) {
|
|
12091
12421
|
if (!validated) {
|
|
12092
12422
|
this.completeOp("updateOne", startedAt, "bad_request" /* BadRequest */, _filter);
|
|
12093
12423
|
return { success: false, kind: "error", code: "bad_request" /* BadRequest */ };
|
|
12094
12424
|
}
|
|
12095
|
-
} else if ((0,
|
|
12425
|
+
} else if ((0, import_utils35.isArray)(validated)) {
|
|
12096
12426
|
if (validated.length > 0) {
|
|
12097
12427
|
this.completeOp("updateOne", startedAt, "bad_request" /* BadRequest */, _filter);
|
|
12098
12428
|
return { success: false, kind: "error", code: "bad_request" /* BadRequest */, errors: validated };
|
|
@@ -12112,10 +12442,10 @@ var Service = class extends Base {
|
|
|
12112
12442
|
const diffExcludeFields = [this.options.documentPermissionField, "__v"];
|
|
12113
12443
|
this.asServiceHookContext(context).diff = (d) => {
|
|
12114
12444
|
context.changes = (0, import_just_diff.diff)(
|
|
12115
|
-
(0,
|
|
12116
|
-
(0,
|
|
12445
|
+
(0, import_utils35.omit)(context.originalDocumentSnapshot, diffExcludeFields),
|
|
12446
|
+
(0, import_utils35.omit)(d.toObject({ virtuals: false }), diffExcludeFields)
|
|
12117
12447
|
) || [];
|
|
12118
|
-
context.modifiedPaths = (0,
|
|
12448
|
+
context.modifiedPaths = (0, import_utils35.uniq)(context.changes.map((di) => di.path.length > 0 ? String(di.path[0]) : ""));
|
|
12119
12449
|
};
|
|
12120
12450
|
doc = assertModelDocument(await this.afterPersist(doc, "update", context), this.modelName, "afterPersist");
|
|
12121
12451
|
context.currentDocument = doc;
|
|
@@ -12203,7 +12533,7 @@ var Service = class extends Base {
|
|
|
12203
12533
|
const upsertOptions = this.resolveUpsertOptions(options);
|
|
12204
12534
|
const updateIntent = captureModelServiceIntent(this, "updateOne", upsertArgs, upsertOptions);
|
|
12205
12535
|
const createIntent = captureModelServiceIntent(this, "create", upsertArgs, upsertOptions);
|
|
12206
|
-
const related = (0,
|
|
12536
|
+
const related = (0, import_utils35.uniqBy)(
|
|
12207
12537
|
[...this.captureRelated(updateIntent.args), ...this.captureRelated(createIntent.args)],
|
|
12208
12538
|
(target) => target.path
|
|
12209
12539
|
);
|
|
@@ -12644,7 +12974,7 @@ var Service = class extends Base {
|
|
|
12644
12974
|
return resolveExistsOptions(this, options);
|
|
12645
12975
|
}
|
|
12646
12976
|
async getFieldPermissionAccess(ids) {
|
|
12647
|
-
const uniqueIds = (0,
|
|
12977
|
+
const uniqueIds = (0, import_utils35.compact)((0, import_utils35.uniqBy)(ids, (id) => String(id)).map((id) => String(id)));
|
|
12648
12978
|
if (uniqueIds.length === 0) {
|
|
12649
12979
|
return {
|
|
12650
12980
|
readIds: /* @__PURE__ */ new Set(),
|
|
@@ -12690,7 +13020,7 @@ var Service = class extends Base {
|
|
|
12690
13020
|
* (direct/root-entry 200); count measures visible rows, not all updated rows.
|
|
12691
13021
|
*/
|
|
12692
13022
|
async bulkUpdateSub(id, sub, data, options) {
|
|
12693
|
-
return bulkUpdateSub(this, this.persist, id, sub, (0,
|
|
13023
|
+
return bulkUpdateSub(this, this.persist, id, sub, (0, import_utils35.castArray)(data), options);
|
|
12694
13024
|
}
|
|
12695
13025
|
/**
|
|
12696
13026
|
* Append/prepend admitted rows, then return the visible full array (including when
|
|
@@ -12714,7 +13044,7 @@ var Service = class extends Base {
|
|
|
12714
13044
|
};
|
|
12715
13045
|
|
|
12716
13046
|
// src/services/public-service.ts
|
|
12717
|
-
var
|
|
13047
|
+
var import_utils36 = require("@web-ts-toolkit/utils");
|
|
12718
13048
|
init_helpers();
|
|
12719
13049
|
init_permissions_alias();
|
|
12720
13050
|
init_document();
|
|
@@ -12840,7 +13170,7 @@ var PublicService = class extends Service {
|
|
|
12840
13170
|
let d = toObject(doc);
|
|
12841
13171
|
d = await this.decorate(d, "create", context);
|
|
12842
13172
|
d = this.runTasks(d, tasks);
|
|
12843
|
-
if (select) d = copyPermissionsAlias(d, (0,
|
|
13173
|
+
if (select) d = copyPermissionsAlias(d, (0, import_utils36.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]));
|
|
12844
13174
|
return d;
|
|
12845
13175
|
}
|
|
12846
13176
|
);
|
|
@@ -13059,8 +13389,8 @@ var PublicService = class extends Service {
|
|
|
13059
13389
|
let d = toObject(doc);
|
|
13060
13390
|
d = await this.decorate(d, "update", context);
|
|
13061
13391
|
d = this.runTasks(d, tasks);
|
|
13062
|
-
if (select) d = copyPermissionsAlias(d, (0,
|
|
13063
|
-
else if (!returningAll) d = copyPermissionsAlias(d, (0,
|
|
13392
|
+
if (select) d = copyPermissionsAlias(d, (0, import_utils36.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]));
|
|
13393
|
+
else if (!returningAll) d = copyPermissionsAlias(d, (0, import_utils36.pick)(d, returningKeys));
|
|
13064
13394
|
return d;
|
|
13065
13395
|
}
|
|
13066
13396
|
);
|
|
@@ -13143,8 +13473,8 @@ var PublicService = class extends Service {
|
|
|
13143
13473
|
let d = toObject(doc);
|
|
13144
13474
|
d = await this.decorate(d, "update", context);
|
|
13145
13475
|
d = this.runTasks(d, tasks2);
|
|
13146
|
-
if (select) d = copyPermissionsAlias(d, (0,
|
|
13147
|
-
else if (!returningAll) d = copyPermissionsAlias(d, (0,
|
|
13476
|
+
if (select) d = copyPermissionsAlias(d, (0, import_utils36.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]));
|
|
13477
|
+
else if (!returningAll) d = copyPermissionsAlias(d, (0, import_utils36.pick)(d, returningKeys));
|
|
13148
13478
|
return d;
|
|
13149
13479
|
}
|
|
13150
13480
|
);
|
|
@@ -13169,7 +13499,7 @@ var PublicService = class extends Service {
|
|
|
13169
13499
|
d = await this.decorate(d, "create", context);
|
|
13170
13500
|
d = this.runTasks(d, tasks);
|
|
13171
13501
|
if (createSelect)
|
|
13172
|
-
d = copyPermissionsAlias(d, (0,
|
|
13502
|
+
d = copyPermissionsAlias(d, (0, import_utils36.pick)(d, [...normalizeSelect(createSelect), ...this.baseFieldsExt]));
|
|
13173
13503
|
return d;
|
|
13174
13504
|
}
|
|
13175
13505
|
);
|
|
@@ -13314,7 +13644,7 @@ var PublicService = class extends Service {
|
|
|
13314
13644
|
init_options();
|
|
13315
13645
|
init_data_values();
|
|
13316
13646
|
init_helpers();
|
|
13317
|
-
var
|
|
13647
|
+
var import_utils37 = require("@web-ts-toolkit/utils");
|
|
13318
13648
|
init_request_complexity();
|
|
13319
13649
|
init_runtime_context();
|
|
13320
13650
|
init_runtime();
|
|
@@ -13343,7 +13673,7 @@ var DataService = class {
|
|
|
13343
13673
|
let doc = await findElement(this.data, _filter);
|
|
13344
13674
|
if (!doc) return { success: false, kind: "error", code: "not_found" /* NotFound */, query };
|
|
13345
13675
|
doc = await this.trimOutputFields(doc, access);
|
|
13346
|
-
if (_select.length > 0) doc = (0,
|
|
13676
|
+
if (_select.length > 0) doc = (0, import_utils37.pick)(doc, _select);
|
|
13347
13677
|
return {
|
|
13348
13678
|
success: true,
|
|
13349
13679
|
kind: "single",
|
|
@@ -13389,13 +13719,13 @@ var DataService = class {
|
|
|
13389
13719
|
const totalCount = docs.length;
|
|
13390
13720
|
if (sort) {
|
|
13391
13721
|
const normalizedSort = normalizeSortForOrderBy(sort);
|
|
13392
|
-
docs = (0,
|
|
13722
|
+
docs = (0, import_utils37.orderBy)(docs, normalizedSort.fields, normalizedSort.orders);
|
|
13393
13723
|
}
|
|
13394
13724
|
const pagedDocs = docs.slice(query.skip, query.limit && query.skip + query.limit);
|
|
13395
13725
|
const { maxHookConcurrency } = this.getRequestComplexity();
|
|
13396
13726
|
const trimmed = await mapWithConcurrencyLimit(pagedDocs, maxHookConcurrency, async (doc) => {
|
|
13397
13727
|
doc = await this.trimOutputFields(doc, "list");
|
|
13398
|
-
if (_select.length > 0) doc = (0,
|
|
13728
|
+
if (_select.length > 0) doc = (0, import_utils37.pick)(doc, _select);
|
|
13399
13729
|
return copyDataValue(doc);
|
|
13400
13730
|
});
|
|
13401
13731
|
if (!hasExplicitLimit && trimmed.length === totalCount) {
|
|
@@ -13470,10 +13800,10 @@ var DataService = class {
|
|
|
13470
13800
|
init_helpers();
|
|
13471
13801
|
|
|
13472
13802
|
// src/processors.ts
|
|
13473
|
-
var
|
|
13803
|
+
var import_utils38 = require("@web-ts-toolkit/utils");
|
|
13474
13804
|
init_permissions_alias();
|
|
13475
13805
|
function cloneProcessorValue(value) {
|
|
13476
|
-
const copy = (0,
|
|
13806
|
+
const copy = (0, import_utils38.cloneDeep)(value);
|
|
13477
13807
|
copyPermissionsAliasGraph(value, copy);
|
|
13478
13808
|
return copy;
|
|
13479
13809
|
}
|
|
@@ -13511,10 +13841,10 @@ function resolveLeafParents(obj, src) {
|
|
|
13511
13841
|
for (let ind = 0; ind < segs.length - 1; ind += 1) {
|
|
13512
13842
|
const seg = segs[ind];
|
|
13513
13843
|
targets = targets.reduce((ret, target) => {
|
|
13514
|
-
if (!(0,
|
|
13844
|
+
if (!(0, import_utils38.isPlainObject)(target)) return ret;
|
|
13515
13845
|
const targetObject = target;
|
|
13516
13846
|
const next = targetObject[seg];
|
|
13517
|
-
if ((0,
|
|
13847
|
+
if ((0, import_utils38.isArray)(next)) {
|
|
13518
13848
|
for (const item of next) {
|
|
13519
13849
|
ret.push(item);
|
|
13520
13850
|
}
|
|
@@ -13524,8 +13854,8 @@ function resolveLeafParents(obj, src) {
|
|
|
13524
13854
|
}
|
|
13525
13855
|
const leaf = segs[segs.length - 1];
|
|
13526
13856
|
const pairs = [];
|
|
13527
|
-
(0,
|
|
13528
|
-
if (!(0,
|
|
13857
|
+
(0, import_utils38.forEach)(targets, (target) => {
|
|
13858
|
+
if (!(0, import_utils38.isPlainObject)(target)) return;
|
|
13529
13859
|
pairs.push({ parent: target, leaf });
|
|
13530
13860
|
});
|
|
13531
13861
|
return pairs;
|
|
@@ -13534,7 +13864,7 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
|
|
|
13534
13864
|
const mutable = options.mutable !== false;
|
|
13535
13865
|
const idField = options.idField ?? "_id";
|
|
13536
13866
|
const obj = mutable ? docObject : cloneProcessorValue(docObject);
|
|
13537
|
-
(0,
|
|
13867
|
+
(0, import_utils38.forEach)(Array.isArray(operations) ? operations : [], (op) => {
|
|
13538
13868
|
if (!op || typeof op.src !== "string" || typeof op.dest !== "string") return;
|
|
13539
13869
|
const src = op.src;
|
|
13540
13870
|
const dest = op.dest;
|
|
@@ -13543,19 +13873,19 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
|
|
|
13543
13873
|
assertSafePath(dest);
|
|
13544
13874
|
let targets = [obj];
|
|
13545
13875
|
const segs = src.split(".");
|
|
13546
|
-
(0,
|
|
13876
|
+
(0, import_utils38.forEach)(segs, (seg, ind) => {
|
|
13547
13877
|
if (segs.length === ind + 1) {
|
|
13548
|
-
(0,
|
|
13549
|
-
if (!(0,
|
|
13878
|
+
(0, import_utils38.forEach)(targets, (target) => {
|
|
13879
|
+
if (!(0, import_utils38.isPlainObject)(target)) return;
|
|
13550
13880
|
const targetObject = target;
|
|
13551
13881
|
const leaf = targetObject[seg];
|
|
13552
13882
|
const sourceForDest = leaf;
|
|
13553
13883
|
let depopulated;
|
|
13554
|
-
if ((0,
|
|
13884
|
+
if ((0, import_utils38.isArray)(leaf)) {
|
|
13555
13885
|
if (leaf.length === 0) {
|
|
13556
13886
|
depopulated = [];
|
|
13557
|
-
} else if (leaf.every((item) => (0,
|
|
13558
|
-
depopulated = (0,
|
|
13887
|
+
} else if (leaf.every((item) => (0, import_utils38.isPlainObject)(item))) {
|
|
13888
|
+
depopulated = (0, import_utils38.map)(leaf, idField).map((id, i) => {
|
|
13559
13889
|
if (id === void 0) {
|
|
13560
13890
|
failMissingId(`${src}[${i}]`);
|
|
13561
13891
|
}
|
|
@@ -13564,8 +13894,8 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
|
|
|
13564
13894
|
} else {
|
|
13565
13895
|
return;
|
|
13566
13896
|
}
|
|
13567
|
-
} else if ((0,
|
|
13568
|
-
const id = (0,
|
|
13897
|
+
} else if ((0, import_utils38.isPlainObject)(leaf)) {
|
|
13898
|
+
const id = (0, import_utils38.get)(leaf, idField);
|
|
13569
13899
|
if (id === void 0) {
|
|
13570
13900
|
failMissingId(src);
|
|
13571
13901
|
}
|
|
@@ -13573,15 +13903,15 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
|
|
|
13573
13903
|
} else {
|
|
13574
13904
|
return;
|
|
13575
13905
|
}
|
|
13576
|
-
(0,
|
|
13577
|
-
(0,
|
|
13906
|
+
(0, import_utils38.set)(targetObject, dest, sourceForDest);
|
|
13907
|
+
(0, import_utils38.set)(targetObject, seg, depopulated);
|
|
13578
13908
|
});
|
|
13579
13909
|
} else {
|
|
13580
13910
|
targets = targets.reduce((ret, target) => {
|
|
13581
|
-
if (!(0,
|
|
13911
|
+
if (!(0, import_utils38.isPlainObject)(target)) return ret;
|
|
13582
13912
|
const targetObject = target;
|
|
13583
13913
|
const next = targetObject[seg];
|
|
13584
|
-
if ((0,
|
|
13914
|
+
if ((0, import_utils38.isArray)(next)) {
|
|
13585
13915
|
for (const item of next) {
|
|
13586
13916
|
ret.push(item);
|
|
13587
13917
|
}
|
|
@@ -13596,7 +13926,7 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
|
|
|
13596
13926
|
var copyPaths = (docObject, operations, options = { mutable: true }) => {
|
|
13597
13927
|
const mutable = options.mutable !== false;
|
|
13598
13928
|
const obj = mutable ? docObject : cloneProcessorValue(docObject);
|
|
13599
|
-
(0,
|
|
13929
|
+
(0, import_utils38.forEach)(Array.isArray(operations) ? operations : [], (op) => {
|
|
13600
13930
|
if (!op || typeof op.src !== "string" || typeof op.dest !== "string") return;
|
|
13601
13931
|
const src = op.src;
|
|
13602
13932
|
const dest = op.dest;
|
|
@@ -13604,9 +13934,9 @@ var copyPaths = (docObject, operations, options = { mutable: true }) => {
|
|
|
13604
13934
|
assertSafePath(src, "copyPaths");
|
|
13605
13935
|
assertSafePath(dest, "copyPaths");
|
|
13606
13936
|
if (src === dest) return;
|
|
13607
|
-
(0,
|
|
13608
|
-
if (!(0,
|
|
13609
|
-
(0,
|
|
13937
|
+
(0, import_utils38.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
|
|
13938
|
+
if (!(0, import_utils38.hasOwn)(parent, leaf)) return;
|
|
13939
|
+
(0, import_utils38.set)(parent, dest, cloneProcessorValue(parent[leaf]));
|
|
13610
13940
|
});
|
|
13611
13941
|
});
|
|
13612
13942
|
return obj;
|
|
@@ -13614,7 +13944,7 @@ var copyPaths = (docObject, operations, options = { mutable: true }) => {
|
|
|
13614
13944
|
var movePaths = (docObject, operations, options = { mutable: true }) => {
|
|
13615
13945
|
const mutable = options.mutable !== false;
|
|
13616
13946
|
const obj = mutable ? docObject : cloneProcessorValue(docObject);
|
|
13617
|
-
(0,
|
|
13947
|
+
(0, import_utils38.forEach)(Array.isArray(operations) ? operations : [], (op) => {
|
|
13618
13948
|
if (!op || typeof op.src !== "string" || typeof op.dest !== "string") return;
|
|
13619
13949
|
const src = op.src;
|
|
13620
13950
|
const dest = op.dest;
|
|
@@ -13622,10 +13952,10 @@ var movePaths = (docObject, operations, options = { mutable: true }) => {
|
|
|
13622
13952
|
assertSafePath(src, "movePaths");
|
|
13623
13953
|
assertSafePath(dest, "movePaths");
|
|
13624
13954
|
if (src === dest) return;
|
|
13625
|
-
(0,
|
|
13626
|
-
if (!(0,
|
|
13955
|
+
(0, import_utils38.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
|
|
13956
|
+
if (!(0, import_utils38.hasOwn)(parent, leaf)) return;
|
|
13627
13957
|
const value = cloneProcessorValue(parent[leaf]);
|
|
13628
|
-
(0,
|
|
13958
|
+
(0, import_utils38.set)(parent, dest, value);
|
|
13629
13959
|
if (dest === leaf || dest.startsWith(`${leaf}.`)) return;
|
|
13630
13960
|
delete parent[leaf];
|
|
13631
13961
|
});
|
|
@@ -13637,7 +13967,7 @@ var sliceArrays = (docObject, operations, options = { mutable: true, maxSlice: D
|
|
|
13637
13967
|
const maxSlice = options.maxSlice ?? DEFAULT_MAX_SLICE;
|
|
13638
13968
|
assertNonNegativeSafeInteger(maxSlice, "maxSlice", "sliceArrays");
|
|
13639
13969
|
const obj = mutable ? docObject : cloneProcessorValue(docObject);
|
|
13640
|
-
(0,
|
|
13970
|
+
(0, import_utils38.forEach)(Array.isArray(operations) ? operations : [], (op) => {
|
|
13641
13971
|
if (!op || typeof op.src !== "string") return;
|
|
13642
13972
|
const src = op.src;
|
|
13643
13973
|
if (src.length === 0) return;
|
|
@@ -13654,15 +13984,15 @@ var sliceArrays = (docObject, operations, options = { mutable: true, maxSlice: D
|
|
|
13654
13984
|
assertNonNegativeSafeInteger(op.limit, "limit", "sliceArrays");
|
|
13655
13985
|
limit = Math.min(op.limit, maxSlice);
|
|
13656
13986
|
}
|
|
13657
|
-
(0,
|
|
13987
|
+
(0, import_utils38.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
|
|
13658
13988
|
const leafValue = parent[leaf];
|
|
13659
|
-
if (!(0,
|
|
13989
|
+
if (!(0, import_utils38.isArray)(leafValue)) return;
|
|
13660
13990
|
const end = typeof limit === "undefined" ? void 0 : skip + limit;
|
|
13661
13991
|
const window = leafValue.slice(skip, end);
|
|
13662
13992
|
if (typeof rawDest === "undefined") {
|
|
13663
|
-
(0,
|
|
13993
|
+
(0, import_utils38.set)(parent, leaf, window);
|
|
13664
13994
|
} else {
|
|
13665
|
-
(0,
|
|
13995
|
+
(0, import_utils38.set)(parent, rawDest, window);
|
|
13666
13996
|
}
|
|
13667
13997
|
});
|
|
13668
13998
|
});
|
|
@@ -13671,27 +14001,27 @@ var sliceArrays = (docObject, operations, options = { mutable: true, maxSlice: D
|
|
|
13671
14001
|
var countPaths = (docObject, operations, options = { mutable: true }) => {
|
|
13672
14002
|
const mutable = options.mutable !== false;
|
|
13673
14003
|
const obj = mutable ? docObject : cloneProcessorValue(docObject);
|
|
13674
|
-
(0,
|
|
14004
|
+
(0, import_utils38.forEach)(Array.isArray(operations) ? operations : [], (op) => {
|
|
13675
14005
|
if (!op || typeof op.src !== "string" || typeof op.dest !== "string") return;
|
|
13676
14006
|
const src = op.src;
|
|
13677
14007
|
const dest = op.dest;
|
|
13678
14008
|
if (src.length === 0 || dest.length === 0) return;
|
|
13679
14009
|
assertSafePath(src, "countPaths");
|
|
13680
14010
|
assertSafePath(dest, "countPaths");
|
|
13681
|
-
(0,
|
|
13682
|
-
if (!(0,
|
|
14011
|
+
(0, import_utils38.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
|
|
14012
|
+
if (!(0, import_utils38.hasOwn)(parent, leaf)) return;
|
|
13683
14013
|
const leafValue = parent[leaf];
|
|
13684
14014
|
let count;
|
|
13685
|
-
if ((0,
|
|
14015
|
+
if ((0, import_utils38.isArray)(leafValue)) {
|
|
13686
14016
|
count = leafValue.length;
|
|
13687
|
-
} else if ((0,
|
|
14017
|
+
} else if ((0, import_utils38.isPlainObject)(leafValue)) {
|
|
13688
14018
|
count = Object.keys(leafValue).length;
|
|
13689
14019
|
} else if (leafValue === null || typeof leafValue === "undefined") {
|
|
13690
14020
|
count = 0;
|
|
13691
14021
|
} else {
|
|
13692
14022
|
count = 1;
|
|
13693
14023
|
}
|
|
13694
|
-
(0,
|
|
14024
|
+
(0, import_utils38.set)(parent, dest, count);
|
|
13695
14025
|
});
|
|
13696
14026
|
});
|
|
13697
14027
|
return obj;
|
|
@@ -13699,15 +14029,15 @@ var countPaths = (docObject, operations, options = { mutable: true }) => {
|
|
|
13699
14029
|
var maskPaths = (docObject, operations, options = { mutable: true }) => {
|
|
13700
14030
|
const mutable = options.mutable !== false;
|
|
13701
14031
|
const obj = mutable ? docObject : cloneProcessorValue(docObject);
|
|
13702
|
-
(0,
|
|
14032
|
+
(0, import_utils38.forEach)(Array.isArray(operations) ? operations : [], (op) => {
|
|
13703
14033
|
if (!op || typeof op.src !== "string") return;
|
|
13704
14034
|
const src = op.src;
|
|
13705
14035
|
if (src.length === 0) return;
|
|
13706
14036
|
assertSafePath(src, "maskPaths");
|
|
13707
14037
|
const replacement = Object.prototype.hasOwnProperty.call(op, "replacement") ? op.replacement : DEFAULT_MASK_REPLACEMENT;
|
|
13708
|
-
(0,
|
|
13709
|
-
if (!(0,
|
|
13710
|
-
(0,
|
|
14038
|
+
(0, import_utils38.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
|
|
14039
|
+
if (!(0, import_utils38.hasOwn)(parent, leaf)) return;
|
|
14040
|
+
(0, import_utils38.set)(parent, leaf, replacement);
|
|
13711
14041
|
});
|
|
13712
14042
|
});
|
|
13713
14043
|
return obj;
|
|
@@ -13762,6 +14092,8 @@ init_core_shared();
|
|
|
13762
14092
|
init_virtual_projection();
|
|
13763
14093
|
init_populate_target();
|
|
13764
14094
|
init_model_output_planning();
|
|
14095
|
+
init_authorization_snapshot();
|
|
14096
|
+
init_document();
|
|
13765
14097
|
init_output_field_filter();
|
|
13766
14098
|
init_request_work();
|
|
13767
14099
|
var emptyPermissionLeaf = () => ({ $: "_" });
|
|
@@ -13779,10 +14111,10 @@ var Core = class {
|
|
|
13779
14111
|
getIdentifier(modelName) {
|
|
13780
14112
|
const resolveIdFilter = getModelOption(modelName, "resolveIdFilter");
|
|
13781
14113
|
const idField = getModelOption(modelName, "idField");
|
|
13782
|
-
if ((0,
|
|
14114
|
+
if ((0, import_utils39.isFunction)(resolveIdFilter)) {
|
|
13783
14115
|
return null;
|
|
13784
14116
|
}
|
|
13785
|
-
if ((0,
|
|
14117
|
+
if ((0, import_utils39.isString)(idField)) {
|
|
13786
14118
|
return idField;
|
|
13787
14119
|
}
|
|
13788
14120
|
return "_id";
|
|
@@ -13872,17 +14204,11 @@ var Core = class {
|
|
|
13872
14204
|
return this.genSelect(modelName, access, targetFields, options);
|
|
13873
14205
|
}
|
|
13874
14206
|
/** Persisted request-only populate admission; fetch planning is not field authority. */
|
|
13875
|
-
async requestPopulateSelect(
|
|
14207
|
+
async requestPopulateSelect(configuration, permissions, access, targetFields = null, scopePath = []) {
|
|
13876
14208
|
const subPaths = scopePath.flatMap((part) => [part, "sub"]);
|
|
13877
|
-
const permissionSchema =
|
|
13878
|
-
const
|
|
13879
|
-
|
|
13880
|
-
try {
|
|
13881
|
-
const runtime = getActiveRuntime() ?? defaultRuntime;
|
|
13882
|
-
virtualNames = runtime.getVirtualNames(modelName, subPaths);
|
|
13883
|
-
} catch {
|
|
13884
|
-
virtualNames = [];
|
|
13885
|
-
}
|
|
14209
|
+
const permissionSchema = (0, import_utils39.get)(configuration, ["permissionSchema", ...subPaths]);
|
|
14210
|
+
const prefix = scopePath.length ? `${scopePath.join(".")}.` : "";
|
|
14211
|
+
const virtualNames = (configuration.catalog.virtualPaths ?? []).filter((path) => path.startsWith(prefix)).map((path) => path.slice(prefix.length)).filter((path) => !path.includes("."));
|
|
13886
14212
|
return resolveSelectForRequest({
|
|
13887
14213
|
req: this.req,
|
|
13888
14214
|
permissionSchema,
|
|
@@ -13901,17 +14227,25 @@ var Core = class {
|
|
|
13901
14227
|
assertPublicAdmission(_populate, "populate");
|
|
13902
14228
|
assertPopulateAccess(access);
|
|
13903
14229
|
if (!_populate) return [];
|
|
13904
|
-
|
|
13905
|
-
for (const p of
|
|
13906
|
-
if (!(0,
|
|
13907
|
-
}
|
|
13908
|
-
|
|
14230
|
+
const descriptors = copyAuthorizationValue(Array.isArray(_populate) ? _populate : [_populate], true);
|
|
14231
|
+
for (const p of descriptors) {
|
|
14232
|
+
if (!(0, import_utils39.isString)(p)) assertPopulateAccess(p.access);
|
|
14233
|
+
}
|
|
14234
|
+
const runtime = this.requestRuntime;
|
|
14235
|
+
const globalOptions = modelServiceGlobalOptions(this, runtime);
|
|
14236
|
+
const relatedTargets = captureRelatedTargets(runtime, modelName, { populate: descriptors }, 0, globalOptions);
|
|
14237
|
+
const sourceConfiguration = captureModelAuthorizationConfiguration(runtime, modelName, void 0, globalOptions);
|
|
14238
|
+
const originalPermissions = this.getGlobalPermissions();
|
|
14239
|
+
const permissions = new permission_default(
|
|
14240
|
+
Object.fromEntries(originalPermissions.keys.map((key) => [key, originalPermissions.has(key)]))
|
|
14241
|
+
);
|
|
14242
|
+
const populate = (0, import_utils39.compact)(
|
|
13909
14243
|
await Promise.all(
|
|
13910
|
-
|
|
13911
|
-
const populateAccess = !(0,
|
|
14244
|
+
descriptors.map(async (p) => {
|
|
14245
|
+
const populateAccess = !(0, import_utils39.isString)(p) && p.access ? p.access : access;
|
|
13912
14246
|
assertPopulateAccess(populateAccess);
|
|
13913
|
-
const originalSelect = (0,
|
|
13914
|
-
const ret = (0,
|
|
14247
|
+
const originalSelect = (0, import_utils39.isString)(p) ? void 0 : p.select;
|
|
14248
|
+
const ret = (0, import_utils39.isString)(p) ? { path: p } : {
|
|
13915
14249
|
path: p.path,
|
|
13916
14250
|
select: normalizeSelect(p.select)
|
|
13917
14251
|
};
|
|
@@ -13919,78 +14253,86 @@ var Core = class {
|
|
|
13919
14253
|
const pathForSourcePermission = scopePrefix && ret.path.startsWith(`${scopePrefix}.`) ? ret.path.slice(scopePrefix.length + 1) : ret.path;
|
|
13920
14254
|
const parentPath = pathForSourcePermission.includes(".") ? pathForSourcePermission.split(".")[0] : pathForSourcePermission;
|
|
13921
14255
|
const allowedParentPaths = await this.requestPopulateSelect(
|
|
13922
|
-
|
|
14256
|
+
sourceConfiguration,
|
|
14257
|
+
permissions,
|
|
13923
14258
|
populateAccess,
|
|
13924
14259
|
[parentPath],
|
|
13925
14260
|
scopePath
|
|
13926
14261
|
);
|
|
13927
14262
|
if (!allowedParentPaths.includes(parentPath)) return null;
|
|
13928
|
-
const
|
|
13929
|
-
if (!
|
|
13930
|
-
const
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
14263
|
+
const target = relatedTargets.find((entry) => entry.path === ret.path);
|
|
14264
|
+
if (!target) return null;
|
|
14265
|
+
const refModelName = target.modelName;
|
|
14266
|
+
const targetConfiguration = target.configuration;
|
|
14267
|
+
if (targetConfiguration.requireOperationAccessForPopulateQueries !== false && !await withCapturedModelOperationGuard(
|
|
14268
|
+
this,
|
|
14269
|
+
refModelName,
|
|
14270
|
+
populateAccess,
|
|
14271
|
+
getCapturedAuthorizationOption(targetConfiguration, `operationAccess.${populateAccess}`),
|
|
14272
|
+
permissions,
|
|
14273
|
+
() => this.isAllowed(refModelName, populateAccess)
|
|
14274
|
+
)) {
|
|
13938
14275
|
return null;
|
|
13939
14276
|
}
|
|
13940
|
-
ret.select = await this.requestPopulateSelect(
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
14277
|
+
ret.select = await this.requestPopulateSelect(
|
|
14278
|
+
targetConfiguration,
|
|
14279
|
+
permissions,
|
|
14280
|
+
populateAccess,
|
|
14281
|
+
ret.select
|
|
14282
|
+
);
|
|
14283
|
+
const hookInputs = resolveAlwaysSelectForAccess(
|
|
14284
|
+
targetConfiguration.alwaysSelectFields,
|
|
14285
|
+
populateAccess
|
|
14286
|
+
);
|
|
14287
|
+
ret.select = (0, import_utils39.uniq)([
|
|
14288
|
+
...ret.select,
|
|
14289
|
+
...stripVirtuals(hookInputs, [...targetConfiguration.catalog.virtualPaths ?? []])
|
|
14290
|
+
]);
|
|
14291
|
+
const match = (0, import_utils39.isString)(p) ? {} : p.match ?? {};
|
|
14292
|
+
const filter2 = await resolveAccessFilterForRequest({
|
|
14293
|
+
req: this.req,
|
|
14294
|
+
permissions,
|
|
14295
|
+
cache: this.caches.baseFilter,
|
|
14296
|
+
cacheKey: `${refModelName}_baseFilter_${populateAccess}`,
|
|
14297
|
+
access: populateAccess,
|
|
14298
|
+
filter: deepIsolateValue(match),
|
|
14299
|
+
getOption: (key) => getCapturedAuthorizationOption(targetConfiguration, key)
|
|
14300
|
+
});
|
|
13944
14301
|
if (filter2 === false) return null;
|
|
13945
|
-
ret.match = filter2;
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
(t) => t !== "-_id" && !t.includes(".sub.")
|
|
13980
|
-
);
|
|
13981
|
-
if (!merged.includes("_id")) merged.push("_id");
|
|
13982
|
-
ret.select = merged;
|
|
13983
|
-
setPopulateTargetMeta(ret, {
|
|
13984
|
-
targetModelName: refModelName,
|
|
13985
|
-
virtualAccess: planAccess,
|
|
13986
|
-
outputAccess: planAccess,
|
|
13987
|
-
docPermissionsAccess: planAccess,
|
|
13988
|
-
requestedSelect: originalSelect,
|
|
13989
|
-
plan: targetPlan,
|
|
13990
|
-
snapshot: targetSnapshot
|
|
13991
|
-
});
|
|
13992
|
-
} catch {
|
|
13993
|
-
}
|
|
14302
|
+
ret.match = deepIsolateValue(intersectFilters(match, filter2));
|
|
14303
|
+
const planAccess = populateAccess;
|
|
14304
|
+
const targetSnapshot = targetConfiguration;
|
|
14305
|
+
const targetPlan = planVirtualProjection({
|
|
14306
|
+
receivingModelName: refModelName,
|
|
14307
|
+
snapshot: {
|
|
14308
|
+
permissionSchema: targetSnapshot.permissionSchema,
|
|
14309
|
+
virtuals: targetSnapshot.virtuals,
|
|
14310
|
+
alwaysSelectFields: targetSnapshot.alwaysSelectFields,
|
|
14311
|
+
modelPermissionPrefix: targetSnapshot.modelPermissionPrefix,
|
|
14312
|
+
requireExplicitSelect: targetSnapshot.requireExplicitSelect,
|
|
14313
|
+
documentPermissionField: targetSnapshot.documentPermissionField
|
|
14314
|
+
},
|
|
14315
|
+
virtualAccess: planAccess,
|
|
14316
|
+
outputAccess: planAccess,
|
|
14317
|
+
docPermissionsAccess: planAccess,
|
|
14318
|
+
requestedSelect: originalSelect,
|
|
14319
|
+
internalFetch: { baseFields: ["_id"] },
|
|
14320
|
+
globalPermissions: permissions
|
|
14321
|
+
});
|
|
14322
|
+
const merged = (0, import_utils39.uniq)([...normalizeSelect(ret.select), ...targetPlan.virtualOnlyDeps ?? []]).filter(
|
|
14323
|
+
(t) => t !== "-_id" && !t.includes(".sub.")
|
|
14324
|
+
);
|
|
14325
|
+
if (!merged.includes("_id")) merged.push("_id");
|
|
14326
|
+
ret.select = merged;
|
|
14327
|
+
setPopulateTargetMeta(ret, {
|
|
14328
|
+
targetModelName: refModelName,
|
|
14329
|
+
virtualAccess: planAccess,
|
|
14330
|
+
outputAccess: planAccess,
|
|
14331
|
+
docPermissionsAccess: planAccess,
|
|
14332
|
+
requestedSelect: originalSelect,
|
|
14333
|
+
plan: targetPlan,
|
|
14334
|
+
snapshot: targetSnapshot
|
|
14335
|
+
});
|
|
13994
14336
|
return ret;
|
|
13995
14337
|
})
|
|
13996
14338
|
)
|
|
@@ -13999,10 +14341,10 @@ var Core = class {
|
|
|
13999
14341
|
}
|
|
14000
14342
|
async validate(modelName, allowedData, access, context) {
|
|
14001
14343
|
const validate = getModelOption(modelName, `validate.${access}`, null);
|
|
14002
|
-
if ((0,
|
|
14344
|
+
if ((0, import_utils39.isFunction)(validate)) {
|
|
14003
14345
|
const permissions = this.getGlobalPermissions();
|
|
14004
14346
|
return validate.call(this.req, allowedData, permissions, context);
|
|
14005
|
-
} else if ((0,
|
|
14347
|
+
} else if ((0, import_utils39.isBoolean)(validate) || (0, import_utils39.isArray)(validate)) {
|
|
14006
14348
|
return validate;
|
|
14007
14349
|
} else {
|
|
14008
14350
|
return true;
|
|
@@ -14027,7 +14369,7 @@ var Core = class {
|
|
|
14027
14369
|
const changeOptions = getModelOption(modelName, `onChange`, {});
|
|
14028
14370
|
for (let x = 0; x < context.modifiedPaths.length; x++) {
|
|
14029
14371
|
const mpath = context.modifiedPaths[x];
|
|
14030
|
-
if ((0,
|
|
14372
|
+
if ((0, import_utils39.isFunction)(changeOptions[mpath])) {
|
|
14031
14373
|
await changeOptions[mpath].call(
|
|
14032
14374
|
this.req,
|
|
14033
14375
|
context.originalDocumentSnapshot[mpath],
|
|
@@ -14051,7 +14393,7 @@ var Core = class {
|
|
|
14051
14393
|
async genDocPermissions(modelName, doc, access, context) {
|
|
14052
14394
|
const docPermissionsFn = getModelOption(modelName, `docPermissions.${access}`, null);
|
|
14053
14395
|
let docPermissions = {};
|
|
14054
|
-
if ((0,
|
|
14396
|
+
if ((0, import_utils39.isFunction)(docPermissionsFn)) {
|
|
14055
14397
|
const permissions = this.getGlobalPermissions();
|
|
14056
14398
|
try {
|
|
14057
14399
|
docPermissions = await getRequestWorkState(this.req, this.requestRuntime).hookGate.run(
|
|
@@ -14135,7 +14477,7 @@ var Core = class {
|
|
|
14135
14477
|
readExists ? requestFields("read") : [],
|
|
14136
14478
|
updateExists ? requestFields("update") : []
|
|
14137
14479
|
]);
|
|
14138
|
-
const viewObj = (0,
|
|
14480
|
+
const viewObj = (0, import_utils39.reduce)(
|
|
14139
14481
|
views,
|
|
14140
14482
|
(ret, view) => {
|
|
14141
14483
|
ret[view] = true;
|
|
@@ -14143,7 +14485,7 @@ var Core = class {
|
|
|
14143
14485
|
},
|
|
14144
14486
|
{}
|
|
14145
14487
|
);
|
|
14146
|
-
const editObj = (0,
|
|
14488
|
+
const editObj = (0, import_utils39.reduce)(
|
|
14147
14489
|
edits,
|
|
14148
14490
|
(ret, view) => {
|
|
14149
14491
|
ret[view] = true;
|
|
@@ -14174,9 +14516,9 @@ var Core = class {
|
|
|
14174
14516
|
});
|
|
14175
14517
|
}
|
|
14176
14518
|
runTasks(modelName, docObject, task) {
|
|
14177
|
-
const tasks = (0,
|
|
14519
|
+
const tasks = (0, import_utils39.compact)((0, import_utils39.castArray)(task));
|
|
14178
14520
|
if (tasks.length === 0) return docObject;
|
|
14179
|
-
(0,
|
|
14521
|
+
(0, import_utils39.forEach)(tasks, (task2) => {
|
|
14180
14522
|
const { type, args, options } = task2;
|
|
14181
14523
|
switch (type) {
|
|
14182
14524
|
case "COPY_AND_DEPOPULATE":
|
|
@@ -14246,9 +14588,9 @@ var Core = class {
|
|
|
14246
14588
|
}
|
|
14247
14589
|
const [, field, op] = keys2;
|
|
14248
14590
|
const subOption = getExactModelOption(modelName, `operationAccess.${access}`);
|
|
14249
|
-
if ((0,
|
|
14591
|
+
if ((0, import_utils39.isUndefined)(subOption)) {
|
|
14250
14592
|
const subFieldOption = getExactModelOption(modelName, `operationAccess.subs.${field}`);
|
|
14251
|
-
if ((0,
|
|
14593
|
+
if ((0, import_utils39.isUndefined)(subFieldOption)) {
|
|
14252
14594
|
const opOption = getModelOption(modelName, `operationAccess.${op}`);
|
|
14253
14595
|
return this.canActivate(opOption);
|
|
14254
14596
|
}
|
|
@@ -14314,25 +14656,25 @@ function guard(condition) {
|
|
|
14314
14656
|
const permissions = req[PERMISSIONS];
|
|
14315
14657
|
let cond = condition;
|
|
14316
14658
|
let phas = (key) => permissions.has(key);
|
|
14317
|
-
if ((0,
|
|
14659
|
+
if ((0, import_utils40.isPlainObject)(condition)) {
|
|
14318
14660
|
const { modelName, id, condition: _cond } = condition;
|
|
14319
14661
|
const svc = req.macl.getPublicService(modelName);
|
|
14320
14662
|
const select = getModelOption(modelName, `alwaysSelectFields.read`, void 0);
|
|
14321
|
-
let _id = (0,
|
|
14322
|
-
if ((0,
|
|
14663
|
+
let _id = (0, import_utils40.isString)(id) ? id : null;
|
|
14664
|
+
if ((0, import_utils40.isPlainObject)(id)) {
|
|
14323
14665
|
const { type = "param", key } = id;
|
|
14324
14666
|
if (type === "param") {
|
|
14325
14667
|
const paramValue = req.params[key];
|
|
14326
|
-
_id = (0,
|
|
14668
|
+
_id = (0, import_utils40.isArray)(paramValue) ? paramValue[0] ?? null : paramValue ?? null;
|
|
14327
14669
|
} else if (type === "query") {
|
|
14328
14670
|
const _qval = req.query[key];
|
|
14329
|
-
if ((0,
|
|
14671
|
+
if ((0, import_utils40.isArray)(_qval)) _id = _qval.length > 0 ? _qval[0] : null;
|
|
14330
14672
|
else _id = _qval;
|
|
14331
14673
|
} else {
|
|
14332
14674
|
_id = null;
|
|
14333
14675
|
}
|
|
14334
14676
|
}
|
|
14335
|
-
if (!(0,
|
|
14677
|
+
if (!(0, import_utils40.isString)(_id) || !_id) {
|
|
14336
14678
|
return next(new import_express_json_router5.default.clientErrors.BadRequestError());
|
|
14337
14679
|
}
|
|
14338
14680
|
const result2 = await svc._read(_id, { select });
|
|
@@ -14344,11 +14686,11 @@ function guard(condition) {
|
|
|
14344
14686
|
cond = _cond;
|
|
14345
14687
|
}
|
|
14346
14688
|
const { stringHandler, arrayHandler } = createValidator(phas);
|
|
14347
|
-
if ((0,
|
|
14689
|
+
if ((0, import_utils40.isString)(cond)) {
|
|
14348
14690
|
if (stringHandler(cond)) return next();
|
|
14349
|
-
} else if ((0,
|
|
14691
|
+
} else if ((0, import_utils40.isArray)(cond)) {
|
|
14350
14692
|
if (arrayHandler(cond)) return next();
|
|
14351
|
-
} else if ((0,
|
|
14693
|
+
} else if ((0, import_utils40.isFunction)(cond)) {
|
|
14352
14694
|
const result2 = await cond.call(req, permissions);
|
|
14353
14695
|
if (!!result2) return next();
|
|
14354
14696
|
}
|
|
@@ -14361,7 +14703,7 @@ var import_express2 = __toESM(require("express"));
|
|
|
14361
14703
|
|
|
14362
14704
|
// src/routers/model-router.ts
|
|
14363
14705
|
var import_express_json_router8 = __toESM(require("@web-ts-toolkit/express-json-router"));
|
|
14364
|
-
var
|
|
14706
|
+
var import_utils44 = require("@web-ts-toolkit/utils");
|
|
14365
14707
|
init_logger_helpers();
|
|
14366
14708
|
init_runtime();
|
|
14367
14709
|
init_runtime_context();
|
|
@@ -14495,7 +14837,7 @@ init_request_complexity();
|
|
|
14495
14837
|
|
|
14496
14838
|
// src/validation/common.ts
|
|
14497
14839
|
var import_zod2 = require("zod");
|
|
14498
|
-
var
|
|
14840
|
+
var import_utils41 = require("@web-ts-toolkit/utils");
|
|
14499
14841
|
|
|
14500
14842
|
// src/validation/public-admission-schema.ts
|
|
14501
14843
|
init_public_admission();
|
|
@@ -14624,7 +14966,7 @@ var correlatedFilterSchema = import_zod2.z.record(import_zod2.z.string(), import
|
|
|
14624
14966
|
}
|
|
14625
14967
|
});
|
|
14626
14968
|
var correlatedEmptyOptionsSchema = import_zod2.z.unknown().refine(
|
|
14627
|
-
(value) => value === void 0 || (0,
|
|
14969
|
+
(value) => value === void 0 || (0, import_utils41.isPlainObject)(value) && Object.keys(value).length === 0,
|
|
14628
14970
|
"Correlated include options must be absent or empty"
|
|
14629
14971
|
).optional();
|
|
14630
14972
|
var correlatedPathSchema = import_zod2.z.string().min(1).superRefine((path, ctx) => {
|
|
@@ -14661,7 +15003,7 @@ var correlatedListArgsSchema = import_zod2.z.object({
|
|
|
14661
15003
|
include: import_zod2.z.lazy(() => correlatedNestedIncludeSchema).optional()
|
|
14662
15004
|
}).strict().superRefine((args, ctx) => checkArgsMarkers(args.select, args.sort, ctx));
|
|
14663
15005
|
var correlatedCountArgsSchema = import_zod2.z.unknown().refine(
|
|
14664
|
-
(value) => value === void 0 || (0,
|
|
15006
|
+
(value) => value === void 0 || (0, import_utils41.isPlainObject)(value) && Object.keys(value).length === 0,
|
|
14665
15007
|
"Count includes accept no args"
|
|
14666
15008
|
).optional();
|
|
14667
15009
|
var correlatedReadByIdSchema = import_zod2.z.object({
|
|
@@ -14714,7 +15056,7 @@ var correlatedNestedIncludeSchema = import_zod2.z.union([includeItemSchema, impo
|
|
|
14714
15056
|
var rejectDuplicateCorrelatedPaths = (items, ctx) => {
|
|
14715
15057
|
const seen = /* @__PURE__ */ new Set();
|
|
14716
15058
|
items.forEach((item, index) => {
|
|
14717
|
-
if ((0,
|
|
15059
|
+
if ((0, import_utils41.isPlainObject)(item) && item.mode === "correlated" && typeof item.path === "string") {
|
|
14718
15060
|
if (seen.has(item.path)) {
|
|
14719
15061
|
ctx.addIssue({
|
|
14720
15062
|
code: import_zod2.z.ZodIssueCode.custom,
|
|
@@ -15687,7 +16029,7 @@ var rootQuerySchema = publicBoundarySchema(
|
|
|
15687
16029
|
init_helpers();
|
|
15688
16030
|
|
|
15689
16031
|
// src/routers/shared.ts
|
|
15690
|
-
var
|
|
16032
|
+
var import_utils42 = require("@web-ts-toolkit/utils");
|
|
15691
16033
|
|
|
15692
16034
|
// src/routers/model-router-collection-routes.ts
|
|
15693
16035
|
init_schemas();
|
|
@@ -15718,15 +16060,15 @@ function setModelCollectionRoutes(context) {
|
|
|
15718
16060
|
sort
|
|
15719
16061
|
} = parseQuery(requestSchemas.listQuery, req.query);
|
|
15720
16062
|
const svc = context.getPublicService(req);
|
|
15721
|
-
const includeCount = (0,
|
|
15722
|
-
const includeExtraHeaders = (0,
|
|
16063
|
+
const includeCount = (0, import_utils42.parseBooleanString)(include_count);
|
|
16064
|
+
const includeExtraHeaders = (0, import_utils42.parseBooleanString)(include_extra_headers);
|
|
15723
16065
|
const result2 = await svc._list(
|
|
15724
16066
|
{},
|
|
15725
16067
|
{ select: parseSelectParam(select), sort, skip, limit, page, pageSize: page_size },
|
|
15726
16068
|
{
|
|
15727
|
-
skim: (0,
|
|
15728
|
-
includePermissions: (0,
|
|
15729
|
-
includeFieldPermissions: (0,
|
|
16069
|
+
skim: (0, import_utils42.parseBooleanString)(skim),
|
|
16070
|
+
includePermissions: (0, import_utils42.parseBooleanString)(include_permissions),
|
|
16071
|
+
includeFieldPermissions: (0, import_utils42.parseBooleanString)(include_field_permissions),
|
|
15730
16072
|
includeCount
|
|
15731
16073
|
}
|
|
15732
16074
|
);
|
|
@@ -15786,8 +16128,8 @@ function setModelCollectionRoutes(context) {
|
|
|
15786
16128
|
data,
|
|
15787
16129
|
{},
|
|
15788
16130
|
{
|
|
15789
|
-
includePermissions: (0,
|
|
15790
|
-
includeFieldPermissions: (0,
|
|
16131
|
+
includePermissions: (0, import_utils42.parseBooleanString)(include_permissions),
|
|
16132
|
+
includeFieldPermissions: (0, import_utils42.parseBooleanString)(include_field_permissions)
|
|
15791
16133
|
}
|
|
15792
16134
|
);
|
|
15793
16135
|
handleResultError(result2);
|
|
@@ -15825,8 +16167,8 @@ function setModelCollectionRoutes(context) {
|
|
|
15825
16167
|
finalData,
|
|
15826
16168
|
{ select: finalSelect, populate: finalPopulate, tasks: finalTasks },
|
|
15827
16169
|
{
|
|
15828
|
-
includePermissions: includePermissions ?? (0,
|
|
15829
|
-
includeFieldPermissions: includeFieldPermissions ?? (0,
|
|
16170
|
+
includePermissions: includePermissions ?? (0, import_utils42.parseBooleanString)(include_permissions),
|
|
16171
|
+
includeFieldPermissions: includeFieldPermissions ?? (0, import_utils42.parseBooleanString)(include_field_permissions),
|
|
15830
16172
|
populateAccess
|
|
15831
16173
|
}
|
|
15832
16174
|
);
|
|
@@ -15923,9 +16265,9 @@ function setModelDocumentRoutes(context) {
|
|
|
15923
16265
|
id,
|
|
15924
16266
|
{ select: parseSelectParam(select) },
|
|
15925
16267
|
{
|
|
15926
|
-
includePermissions: (0,
|
|
15927
|
-
includeFieldPermissions: (0,
|
|
15928
|
-
tryList: (0,
|
|
16268
|
+
includePermissions: (0, import_utils42.parseBooleanString)(include_permissions),
|
|
16269
|
+
includeFieldPermissions: (0, import_utils42.parseBooleanString)(include_field_permissions),
|
|
16270
|
+
tryList: (0, import_utils42.parseBooleanString)(try_list)
|
|
15929
16271
|
}
|
|
15930
16272
|
);
|
|
15931
16273
|
handleResultError(result2);
|
|
@@ -16025,9 +16367,9 @@ function setModelDocumentRoutes(context) {
|
|
|
16025
16367
|
data,
|
|
16026
16368
|
{ select: parseSelectParam(select) },
|
|
16027
16369
|
{
|
|
16028
|
-
returningAll: (0,
|
|
16029
|
-
includePermissions: (0,
|
|
16030
|
-
includeFieldPermissions: (0,
|
|
16370
|
+
returningAll: (0, import_utils42.parseBooleanString)(returning_all),
|
|
16371
|
+
includePermissions: (0, import_utils42.parseBooleanString)(include_permissions),
|
|
16372
|
+
includeFieldPermissions: (0, import_utils42.parseBooleanString)(include_field_permissions)
|
|
16031
16373
|
}
|
|
16032
16374
|
);
|
|
16033
16375
|
handleResultError(result2);
|
|
@@ -16076,9 +16418,9 @@ function setModelDocumentRoutes(context) {
|
|
|
16076
16418
|
finalData,
|
|
16077
16419
|
{ select: finalSelect, populate: finalPopulate, tasks: finalTasks },
|
|
16078
16420
|
{
|
|
16079
|
-
returningAll: returningAll ?? (0,
|
|
16080
|
-
includePermissions: includePermissions ?? (0,
|
|
16081
|
-
includeFieldPermissions: includeFieldPermissions ?? (0,
|
|
16421
|
+
returningAll: returningAll ?? (0, import_utils42.parseBooleanString)(returning_all),
|
|
16422
|
+
includePermissions: includePermissions ?? (0, import_utils42.parseBooleanString)(include_permissions),
|
|
16423
|
+
includeFieldPermissions: includeFieldPermissions ?? (0, import_utils42.parseBooleanString)(include_field_permissions),
|
|
16082
16424
|
populateAccess
|
|
16083
16425
|
}
|
|
16084
16426
|
);
|
|
@@ -16109,9 +16451,9 @@ function setModelDocumentRoutes(context) {
|
|
|
16109
16451
|
body,
|
|
16110
16452
|
{},
|
|
16111
16453
|
{
|
|
16112
|
-
returningAll: (0,
|
|
16113
|
-
includePermissions: (0,
|
|
16114
|
-
includeFieldPermissions: (0,
|
|
16454
|
+
returningAll: (0, import_utils42.parseBooleanString)(returning_all),
|
|
16455
|
+
includePermissions: (0, import_utils42.parseBooleanString)(include_permissions),
|
|
16456
|
+
includeFieldPermissions: (0, import_utils42.parseBooleanString)(include_field_permissions)
|
|
16115
16457
|
}
|
|
16116
16458
|
);
|
|
16117
16459
|
handleResultError(result2);
|
|
@@ -16158,9 +16500,9 @@ function setModelDocumentRoutes(context) {
|
|
|
16158
16500
|
finalData,
|
|
16159
16501
|
{ select: finalSelect, populate: finalPopulate, tasks: finalTasks },
|
|
16160
16502
|
{
|
|
16161
|
-
returningAll: returningAll ?? (0,
|
|
16162
|
-
includePermissions: includePermissions ?? (0,
|
|
16163
|
-
includeFieldPermissions: includeFieldPermissions ?? (0,
|
|
16503
|
+
returningAll: returningAll ?? (0, import_utils42.parseBooleanString)(returning_all),
|
|
16504
|
+
includePermissions: includePermissions ?? (0, import_utils42.parseBooleanString)(include_permissions),
|
|
16505
|
+
includeFieldPermissions: includeFieldPermissions ?? (0, import_utils42.parseBooleanString)(include_field_permissions),
|
|
16164
16506
|
populateAccess
|
|
16165
16507
|
}
|
|
16166
16508
|
);
|
|
@@ -16400,11 +16742,11 @@ function setModelSubDocumentRoutes(context) {
|
|
|
16400
16742
|
}
|
|
16401
16743
|
|
|
16402
16744
|
// src/openapi/route-registration.ts
|
|
16403
|
-
var
|
|
16745
|
+
var import_utils43 = require("@web-ts-toolkit/utils");
|
|
16404
16746
|
function registerOpenApiRoute(runtime, basePath, defaultTag, route) {
|
|
16405
16747
|
runtime.registerOpenApiRoute({
|
|
16406
16748
|
...route,
|
|
16407
|
-
path: (0,
|
|
16749
|
+
path: (0, import_utils43.normalizeUrlPath)(basePath + route.path),
|
|
16408
16750
|
tags: route.tags ?? [defaultTag]
|
|
16409
16751
|
});
|
|
16410
16752
|
}
|
|
@@ -16412,8 +16754,8 @@ function registerOpenApiRoute(runtime, basePath, defaultTag, route) {
|
|
|
16412
16754
|
// src/routers/model-router.ts
|
|
16413
16755
|
var clientErrors2 = import_express_json_router8.default.clientErrors;
|
|
16414
16756
|
function setOption(parentKey, optionKey, option) {
|
|
16415
|
-
const key = (0,
|
|
16416
|
-
const value = (0,
|
|
16757
|
+
const key = (0, import_utils44.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
|
|
16758
|
+
const value = (0, import_utils44.isUndefined)(option) ? optionKey : option;
|
|
16417
16759
|
assertMutableRouterOption("model", key);
|
|
16418
16760
|
this.runtime.setModelOption(
|
|
16419
16761
|
this.modelName,
|
|
@@ -16615,7 +16957,7 @@ var ModelRouter = class _ModelRouter {
|
|
|
16615
16957
|
this.runtime = runtime;
|
|
16616
16958
|
this.runtime.setModelOptions(modelName, initialOptions);
|
|
16617
16959
|
this.options = this.runtime.getModelOptions(modelName);
|
|
16618
|
-
this.fullBasePath = (0,
|
|
16960
|
+
this.fullBasePath = (0, import_utils44.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
|
|
16619
16961
|
this.modelName = modelName;
|
|
16620
16962
|
this.router = new import_express_json_router8.default(this.options.basePath, createSetCore(this.runtime), accessRouterResponseHandler);
|
|
16621
16963
|
this.model = new model_default(modelName, this.runtime);
|
|
@@ -16701,13 +17043,13 @@ var ModelRouter = class _ModelRouter {
|
|
|
16701
17043
|
}
|
|
16702
17044
|
logEndpoints() {
|
|
16703
17045
|
runWithRuntime(this.runtime, () => {
|
|
16704
|
-
(0,
|
|
16705
|
-
logInfoMessage(`${(0,
|
|
17046
|
+
(0, import_utils44.forEach)(this.router.getEndpoints(), ({ method, path }) => {
|
|
17047
|
+
logInfoMessage(`${(0, import_utils44.padEnd)(method, 6)} ${(0, import_utils44.normalizeUrlPath)(this.options.parentPath + path)}`);
|
|
16706
17048
|
});
|
|
16707
17049
|
});
|
|
16708
17050
|
}
|
|
16709
17051
|
set(keyOrOptions, value) {
|
|
16710
|
-
if (arguments.length === 2 && (0,
|
|
17052
|
+
if (arguments.length === 2 && (0, import_utils44.isString)(keyOrOptions)) {
|
|
16711
17053
|
assertMutableRouterOption("model", keyOrOptions);
|
|
16712
17054
|
this.runtime.setModelOption(
|
|
16713
17055
|
this.modelName,
|
|
@@ -16715,7 +17057,7 @@ var ModelRouter = class _ModelRouter {
|
|
|
16715
17057
|
value
|
|
16716
17058
|
);
|
|
16717
17059
|
}
|
|
16718
|
-
if (arguments.length === 1 && (0,
|
|
17060
|
+
if (arguments.length === 1 && (0, import_utils44.isPlainObject)(keyOrOptions)) {
|
|
16719
17061
|
assertMutableRouterOptions("model", keyOrOptions);
|
|
16720
17062
|
this.runtime.setModelOptions(
|
|
16721
17063
|
this.modelName,
|
|
@@ -16743,7 +17085,7 @@ var ModelRouter = class _ModelRouter {
|
|
|
16743
17085
|
|
|
16744
17086
|
// src/routers/root-router.ts
|
|
16745
17087
|
var import_express_json_router9 = __toESM(require("@web-ts-toolkit/express-json-router"));
|
|
16746
|
-
var
|
|
17088
|
+
var import_utils45 = require("@web-ts-toolkit/utils");
|
|
16747
17089
|
|
|
16748
17090
|
// src/core-data.ts
|
|
16749
17091
|
init_options();
|
|
@@ -17051,7 +17393,7 @@ var RootRouter = class {
|
|
|
17051
17393
|
this.setRoutes();
|
|
17052
17394
|
}
|
|
17053
17395
|
registerOpenApiRoute(route) {
|
|
17054
|
-
registerOpenApiRoute(this.runtime, (0,
|
|
17396
|
+
registerOpenApiRoute(this.runtime, (0, import_utils45.normalizeUrlPath)(this.basename), "root", route);
|
|
17055
17397
|
}
|
|
17056
17398
|
wrapResult(index, item, result2) {
|
|
17057
17399
|
return {
|
|
@@ -17160,7 +17502,7 @@ var RootRouter = class {
|
|
|
17160
17502
|
groupItemsByOrder(items) {
|
|
17161
17503
|
const groups = /* @__PURE__ */ new Map();
|
|
17162
17504
|
items.forEach((item, index) => {
|
|
17163
|
-
const order = (0,
|
|
17505
|
+
const order = (0, import_utils45.isNumber)(item.order) ? item.order : 0;
|
|
17164
17506
|
const group = groups.get(order);
|
|
17165
17507
|
if (group) {
|
|
17166
17508
|
group.push({ index, item });
|
|
@@ -17231,7 +17573,7 @@ var RootRouter = class {
|
|
|
17231
17573
|
const arrResult = await this.runGroup(req, groupedItems[x]);
|
|
17232
17574
|
results.push(...arrResult);
|
|
17233
17575
|
}
|
|
17234
|
-
return (0,
|
|
17576
|
+
return (0, import_utils45.orderBy)(results, ["index"], ["asc"]);
|
|
17235
17577
|
});
|
|
17236
17578
|
this.registerOpenApiRoute({
|
|
17237
17579
|
method: "post",
|
|
@@ -17249,14 +17591,14 @@ var RootRouter = class {
|
|
|
17249
17591
|
|
|
17250
17592
|
// src/routers/data-router.ts
|
|
17251
17593
|
var import_express_json_router10 = __toESM(require("@web-ts-toolkit/express-json-router"));
|
|
17252
|
-
var
|
|
17594
|
+
var import_utils46 = require("@web-ts-toolkit/utils");
|
|
17253
17595
|
init_runtime();
|
|
17254
17596
|
init_helpers();
|
|
17255
17597
|
init_schemas();
|
|
17256
17598
|
var clientErrors4 = import_express_json_router10.default.clientErrors;
|
|
17257
17599
|
function setOption2(parentKey, optionKey, option) {
|
|
17258
|
-
const key = (0,
|
|
17259
|
-
const value = (0,
|
|
17600
|
+
const key = (0, import_utils46.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
|
|
17601
|
+
const value = (0, import_utils46.isUndefined)(option) ? optionKey : option;
|
|
17260
17602
|
assertMutableRouterOption("data", key);
|
|
17261
17603
|
this.runtime.setDataOption(this.dataName, key, value);
|
|
17262
17604
|
return this;
|
|
@@ -17305,7 +17647,7 @@ var DataRouter = class {
|
|
|
17305
17647
|
this.runtime = runtime;
|
|
17306
17648
|
this.runtime.setDataOptions(dataName, initialOptions);
|
|
17307
17649
|
this.options = this.runtime.getDataOptions(dataName);
|
|
17308
|
-
this.fullBasePath = (0,
|
|
17650
|
+
this.fullBasePath = (0, import_utils46.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
|
|
17309
17651
|
this.dataName = dataName;
|
|
17310
17652
|
this.router = new import_express_json_router10.default(this.options.basePath, createSetDataCore(this.runtime), accessRouterResponseHandler);
|
|
17311
17653
|
this.setCollectionRoutes();
|
|
@@ -17338,8 +17680,8 @@ var DataRouter = class {
|
|
|
17338
17680
|
req.query
|
|
17339
17681
|
);
|
|
17340
17682
|
const svc = this.getService(req);
|
|
17341
|
-
const includeCount = (0,
|
|
17342
|
-
const includeExtraHeaders = (0,
|
|
17683
|
+
const includeCount = (0, import_utils42.parseBooleanString)(include_count);
|
|
17684
|
+
const includeExtraHeaders = (0, import_utils42.parseBooleanString)(include_extra_headers);
|
|
17343
17685
|
const result2 = await svc.find(
|
|
17344
17686
|
{},
|
|
17345
17687
|
{ select: parseSelectParam(select), sort, skip, limit, page, pageSize: page_size },
|
|
@@ -17457,7 +17799,7 @@ var DataRouter = class {
|
|
|
17457
17799
|
});
|
|
17458
17800
|
}
|
|
17459
17801
|
set(keyOrOptions, value) {
|
|
17460
|
-
if (arguments.length === 2 && (0,
|
|
17802
|
+
if (arguments.length === 2 && (0, import_utils46.isString)(keyOrOptions)) {
|
|
17461
17803
|
assertMutableRouterOption("data", keyOrOptions);
|
|
17462
17804
|
this.runtime.setDataOption(
|
|
17463
17805
|
this.dataName,
|
|
@@ -17465,7 +17807,7 @@ var DataRouter = class {
|
|
|
17465
17807
|
value
|
|
17466
17808
|
);
|
|
17467
17809
|
}
|
|
17468
|
-
if (arguments.length === 1 && (0,
|
|
17810
|
+
if (arguments.length === 1 && (0, import_utils46.isPlainObject)(keyOrOptions)) {
|
|
17469
17811
|
assertMutableRouterOptions("data", keyOrOptions);
|
|
17470
17812
|
this.runtime.setDataOptions(this.dataName, keyOrOptions);
|
|
17471
17813
|
}
|
|
@@ -17600,7 +17942,7 @@ function createRuntimeApi(runtime) {
|
|
|
17600
17942
|
const wtt2 = runtimeMiddleware;
|
|
17601
17943
|
wtt2.runtime = runtime;
|
|
17602
17944
|
wtt2.createRouter = function(modelName, options) {
|
|
17603
|
-
if ((0,
|
|
17945
|
+
if ((0, import_utils47.isUndefined)(options)) {
|
|
17604
17946
|
return new RootRouter(modelName, runtime);
|
|
17605
17947
|
}
|
|
17606
17948
|
if (typeof modelName === "string") {
|
|
@@ -17621,10 +17963,10 @@ function createRuntimeApi(runtime) {
|
|
|
17621
17963
|
};
|
|
17622
17964
|
wtt2.combineRoutes = combineRoutes;
|
|
17623
17965
|
wtt2.set = function(keyOrOptions, value) {
|
|
17624
|
-
if (arguments.length === 2 && (0,
|
|
17966
|
+
if (arguments.length === 2 && (0, import_utils47.isString)(keyOrOptions)) {
|
|
17625
17967
|
return runtime.setGlobalOption(keyOrOptions, value);
|
|
17626
17968
|
}
|
|
17627
|
-
if (arguments.length === 1 && (0,
|
|
17969
|
+
if (arguments.length === 1 && (0, import_utils47.isPlainObject)(keyOrOptions)) {
|
|
17628
17970
|
return runtime.setGlobalOptions(keyOrOptions);
|
|
17629
17971
|
}
|
|
17630
17972
|
};
|