vanta-api 1.1.7 → 1.1.8
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/package.json +1 -1
- package/src/api-features.js +74 -69
package/package.json
CHANGED
package/src/api-features.js
CHANGED
|
@@ -33,8 +33,10 @@ export class ApiFeatures {
|
|
|
33
33
|
filter() {
|
|
34
34
|
// Parse and sanitize both query and manual filters
|
|
35
35
|
const queryFilters = this._parseQueryFilters();
|
|
36
|
-
const
|
|
37
|
-
|
|
36
|
+
const merged = this._sanitizeFilters({
|
|
37
|
+
...queryFilters,
|
|
38
|
+
...this.manualFilters,
|
|
39
|
+
});
|
|
38
40
|
const safe = this._applySecurityFilters(merged);
|
|
39
41
|
|
|
40
42
|
if (Object.keys(safe).length) {
|
|
@@ -117,7 +119,7 @@ export class ApiFeatures {
|
|
|
117
119
|
|
|
118
120
|
// Apply lookups
|
|
119
121
|
for (const opt of final) {
|
|
120
|
-
const field = typeof opt ===
|
|
122
|
+
const field = typeof opt === "string" ? opt : opt.path;
|
|
121
123
|
const proj =
|
|
122
124
|
typeof opt === "object" && opt.select
|
|
123
125
|
? opt.select.split(" ").reduce((a, f) => {
|
|
@@ -215,87 +217,90 @@ export class ApiFeatures {
|
|
|
215
217
|
});
|
|
216
218
|
}
|
|
217
219
|
|
|
218
|
-
_parseQueryFilters() {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const
|
|
232
|
-
|
|
220
|
+
_parseQueryFilters() {
|
|
221
|
+
const obj = { ...this.query };
|
|
222
|
+
// پاک کردن پارامترهای سیستماتیک
|
|
223
|
+
["page", "limit", "sort", "fields", "populate"].forEach(
|
|
224
|
+
(k) => delete obj[k]
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
const out = {};
|
|
228
|
+
|
|
229
|
+
for (const [rawKey, rawVal] of Object.entries(obj)) {
|
|
230
|
+
if (typeof rawVal === "object" && !Array.isArray(rawVal)) {
|
|
231
|
+
out[rawKey] = {};
|
|
232
|
+
for (let [op, val] of Object.entries(rawVal)) {
|
|
233
|
+
const cleanOp = op.replace(/^\$/, "");
|
|
234
|
+
if (securityConfig.allowedOperators.includes(cleanOp)) {
|
|
235
|
+
const v = /^[0-9]+$/.test(val) ? parseInt(val, 10) : val;
|
|
236
|
+
out[rawKey][`$${cleanOp}`] = v;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
} else if (/^\w+\[\$?\w+\]$/.test(rawKey)) {
|
|
240
|
+
const [, field, op] = rawKey.match(/^(\w+)\[\$?(\w+)\]$/);
|
|
241
|
+
if (securityConfig.allowedOperators.includes(op)) {
|
|
242
|
+
const v = /^[0-9]+$/.test(rawVal) ? parseInt(rawVal, 10) : rawVal;
|
|
243
|
+
out[field] = { [`$${op}`]: v };
|
|
233
244
|
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
else if (/^\w+\[\$?\w+\]$/.test(rawKey)) {
|
|
237
|
-
const [, field, op] = rawKey.match(/^(\w+)\[\$?(\w+)\]$/);
|
|
238
|
-
if (securityConfig.allowedOperators.includes(op)) {
|
|
239
|
-
const v = /^[0-9]+$/.test(rawVal) ? parseInt(rawVal, 10) : rawVal;
|
|
240
|
-
out[field] = { [`$${op}`]: v };
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
if (typeof rawVal === "string" && rawVal.includes(",")) {
|
|
245
|
-
out[rawKey] = rawVal.split(",");
|
|
246
245
|
} else {
|
|
247
|
-
|
|
246
|
+
if (typeof rawVal === "string" && rawVal.includes(",")) {
|
|
247
|
+
out[rawKey] = rawVal.split(",");
|
|
248
|
+
} else {
|
|
249
|
+
out[rawKey] = rawVal;
|
|
250
|
+
}
|
|
248
251
|
}
|
|
249
252
|
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return out;
|
|
253
|
-
}
|
|
254
253
|
|
|
254
|
+
return out;
|
|
255
|
+
}
|
|
255
256
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
_sanitizeFilters(filters) {
|
|
258
|
+
const resultObj = {};
|
|
259
|
+
const resualt = Object.entries(filters).map((el) => {
|
|
260
|
+
const [keyObj, val] = el;
|
|
259
261
|
if (
|
|
260
|
-
typeof val ===
|
|
261
|
-
val
|
|
262
|
-
|
|
262
|
+
typeof val === "object" &&
|
|
263
|
+
(this.#isStrictObjectId(val["$eq"]) ||
|
|
264
|
+
this.#isStrictObjectId(val["eq"]))
|
|
263
265
|
) {
|
|
264
266
|
const newVal = { ...val };
|
|
265
|
-
if (this.#isStrictObjectId(val[
|
|
266
|
-
newVal[
|
|
267
|
+
if (this.#isStrictObjectId(val["$eq"])) {
|
|
268
|
+
newVal["$eq"] = new ObjectId(val["$eq"]);
|
|
267
269
|
}
|
|
268
|
-
if (this.#isStrictObjectId(val[
|
|
269
|
-
newVal[
|
|
270
|
+
if (this.#isStrictObjectId(val["eq"])) {
|
|
271
|
+
newVal["eq"] = new ObjectId(val["eq"]);
|
|
270
272
|
}
|
|
271
|
-
|
|
273
|
+
resultObj[keyObj] = newVal;
|
|
274
|
+
return;
|
|
272
275
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
if (val === "false") return false;
|
|
277
|
-
|
|
278
|
-
// تبدیل عدد صحیح
|
|
279
|
-
if (typeof val === 'string' && /^[0-9]+$/.test(val)) return parseInt(val, 10);
|
|
280
|
-
|
|
281
|
-
// اگر val یک رشته است و ObjectId معتبر باشد، به ObjectId تبدیل شود
|
|
282
|
-
if (
|
|
283
|
-
typeof val === 'string' &&
|
|
284
|
-
this.#isStrictObjectId(val)
|
|
285
|
-
) {
|
|
286
|
-
return new mongoose.Types.ObjectId(val);
|
|
276
|
+
if (val === "true") {
|
|
277
|
+
resultObj[keyObj] = true;
|
|
278
|
+
return;
|
|
287
279
|
}
|
|
288
|
-
|
|
289
|
-
|
|
280
|
+
if (val === "false") {
|
|
281
|
+
resultObj[keyObj] = false;
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (typeof val === "string" && /^[0-9]+$/.test(val)) {
|
|
285
|
+
resultObj[keyObj] = parseInt(val, 10);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (typeof val === "string" && this.#isStrictObjectId(val)) {
|
|
289
|
+
resultObj[keyObj] = new ObjectId(val);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
resultObj[keyObj] = val;
|
|
290
293
|
});
|
|
294
|
+
return resultObj;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
#isStrictObjectId(id) {
|
|
298
|
+
return (
|
|
299
|
+
typeof id === "string" &&
|
|
300
|
+
mongoose.Types.ObjectId.isValid(id) &&
|
|
301
|
+
new mongoose.Types.ObjectId(id).toString() === id
|
|
302
|
+
);
|
|
291
303
|
}
|
|
292
|
-
#isStrictObjectId(id) {
|
|
293
|
-
return (
|
|
294
|
-
typeof id === 'string' &&
|
|
295
|
-
mongoose.Types.ObjectId.isValid(id) &&
|
|
296
|
-
(new mongoose.Types.ObjectId(id)).toString() === id
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
304
|
|
|
300
305
|
_applySecurityFilters(filters) {
|
|
301
306
|
let res = { ...filters };
|