@lenne.tech/nest-server 11.20.0 → 11.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/common/helpers/db.helper.d.ts +1 -1
- package/dist/core/common/helpers/db.helper.js +10 -4
- package/dist/core/common/helpers/db.helper.js.map +1 -1
- package/dist/core/common/helpers/input.helper.d.ts +1 -1
- package/dist/core/common/helpers/input.helper.js +6 -2
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/interceptors/check-security.interceptor.js +8 -0
- package/dist/core/common/interceptors/check-security.interceptor.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/core/common/helpers/db.helper.ts +13 -6
- package/src/core/common/helpers/input.helper.ts +6 -2
- package/src/core/common/interceptors/check-security.interceptor.ts +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.20.
|
|
3
|
+
"version": "11.20.1",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -550,6 +550,7 @@ export function removeUnresolvedReferences<T = any>(
|
|
|
550
550
|
populated: T,
|
|
551
551
|
populatedOptions: (PopulateOptions | string)[] | PopulateOptions | PopulateOptions[] | string,
|
|
552
552
|
ignoreFirst = true,
|
|
553
|
+
visited: WeakSet<object> = new WeakSet(),
|
|
553
554
|
): T {
|
|
554
555
|
// Check parameter
|
|
555
556
|
if (!populated || !populatedOptions) {
|
|
@@ -558,21 +559,24 @@ export function removeUnresolvedReferences<T = any>(
|
|
|
558
559
|
|
|
559
560
|
// Process array
|
|
560
561
|
if (Array.isArray(populated)) {
|
|
561
|
-
|
|
562
|
+
if (visited.has(populated)) return populated;
|
|
563
|
+
visited.add(populated);
|
|
564
|
+
populated.forEach((p) => removeUnresolvedReferences(p, populatedOptions, false, visited));
|
|
562
565
|
return populated;
|
|
563
566
|
}
|
|
564
567
|
|
|
565
568
|
// Process object
|
|
566
569
|
if (typeof populated === 'object') {
|
|
567
|
-
// populatedOptions is an array
|
|
570
|
+
// populatedOptions is an array — iterate options for the same object
|
|
571
|
+
// Each option targets a different property path, so do not mark populated as visited here
|
|
568
572
|
if (Array.isArray(populatedOptions)) {
|
|
569
573
|
populatedOptions.forEach((po) =>
|
|
570
|
-
removeUnresolvedReferences(populated, ignoreFirst && typeof po === 'object' ? po.populate : po, false),
|
|
574
|
+
removeUnresolvedReferences(populated, ignoreFirst && typeof po === 'object' ? po.populate : po, false, visited),
|
|
571
575
|
);
|
|
572
576
|
return populated;
|
|
573
577
|
}
|
|
574
578
|
|
|
575
|
-
// populatedOptions is a string
|
|
579
|
+
// populatedOptions is a string — leaf operation, no deep recursion risk
|
|
576
580
|
if (typeof populatedOptions === 'string') {
|
|
577
581
|
if (!['_id', 'id'].includes(populatedOptions) && populated[populatedOptions] instanceof Types.ObjectId) {
|
|
578
582
|
populated[populatedOptions] = null;
|
|
@@ -580,13 +584,16 @@ export function removeUnresolvedReferences<T = any>(
|
|
|
580
584
|
return populated;
|
|
581
585
|
}
|
|
582
586
|
|
|
583
|
-
// populatedOptions is
|
|
587
|
+
// populatedOptions is a PopulateOptions object
|
|
584
588
|
if (populatedOptions.path) {
|
|
585
589
|
const key = populatedOptions.path;
|
|
586
590
|
if (!['_id', 'id'].includes(key) && populated[key] instanceof Types.ObjectId) {
|
|
587
591
|
populated[key] = null;
|
|
588
592
|
} else if (populatedOptions.populate) {
|
|
589
|
-
|
|
593
|
+
// Prevent circular reference loops when descending into nested populates
|
|
594
|
+
if (visited.has(populated as object)) return populated;
|
|
595
|
+
visited.add(populated as object);
|
|
596
|
+
removeUnresolvedReferences(populated[key], populatedOptions.populate, false, visited);
|
|
590
597
|
}
|
|
591
598
|
}
|
|
592
599
|
}
|
|
@@ -413,12 +413,16 @@ export function combinePlain(...args: Record<any, any>[]): any {
|
|
|
413
413
|
/**
|
|
414
414
|
* Get deep frozen object
|
|
415
415
|
*/
|
|
416
|
-
export function deepFreeze(object: any) {
|
|
416
|
+
export function deepFreeze(object: any, visited: WeakSet<object> = new WeakSet()) {
|
|
417
417
|
if (!object || typeof object !== 'object') {
|
|
418
418
|
return object;
|
|
419
419
|
}
|
|
420
|
+
if (visited.has(object)) {
|
|
421
|
+
return object;
|
|
422
|
+
}
|
|
423
|
+
visited.add(object);
|
|
420
424
|
for (const [key, value] of Object.entries(object)) {
|
|
421
|
-
object[key] = deepFreeze(value);
|
|
425
|
+
object[key] = deepFreeze(value, visited);
|
|
422
426
|
}
|
|
423
427
|
return Object.freeze(object);
|
|
424
428
|
}
|
|
@@ -116,17 +116,25 @@ export class CheckSecurityInterceptor implements NestInterceptor {
|
|
|
116
116
|
const proto = Object.getPrototypeOf(val);
|
|
117
117
|
return proto === null || proto === Object.prototype || typeof val.constructor === 'function';
|
|
118
118
|
};
|
|
119
|
+
const visited = new WeakSet();
|
|
119
120
|
const removeSecrets = (data: any) => {
|
|
120
121
|
if (!this.config.removeSecretFields || !data || typeof data !== 'object') {
|
|
121
122
|
return data;
|
|
122
123
|
}
|
|
123
124
|
if (Array.isArray(data)) {
|
|
125
|
+
if (visited.has(data)) return data;
|
|
126
|
+
visited.add(data);
|
|
124
127
|
data.forEach(removeSecrets);
|
|
125
128
|
return data;
|
|
126
129
|
}
|
|
127
130
|
if (!isPlainLike(data)) {
|
|
128
131
|
return data;
|
|
129
132
|
}
|
|
133
|
+
// Prevent infinite recursion on circular references
|
|
134
|
+
if (visited.has(data)) {
|
|
135
|
+
return data;
|
|
136
|
+
}
|
|
137
|
+
visited.add(data);
|
|
130
138
|
for (const field of this.config.secretFields) {
|
|
131
139
|
if (field in data && data[field] !== undefined) {
|
|
132
140
|
data[field] = undefined;
|