Skip to content

Commit

Permalink
Merge branch '6.x' into 7.x
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Jan 13, 2025
2 parents ad7b0e0 + e59e342 commit 4fe9a90
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 24 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
6.13.6 / 2025-01-13
===================
* fix: disallow nested $where in populate match

7.8.3 / 2024-11-26
==================
* fix: disallow using $where in match
Expand Down Expand Up @@ -646,7 +650,7 @@
* fix(document): isModified should not be triggered when setting a nested boolean to the same value as previously #12994 [lpizzinidev](https://github.com/lpizzinidev)
* fix(document): save newly set defaults underneath single nested subdocuments #13002 #12905
* fix(update): handle custom discriminator model name when casting update #12947 [wassil](https://github.com/wassil)
* fix(connection): handles unique autoincrement ID for connections #12990 [lpizzinidev](https://github.com/lpizzinidev)
* fix(connection): handles unique autoincrement ID for connections #12990 [lpizzinidev](https://github.com/lpizzinidev)
* fix(types): fix type of options of Model.aggregate #12933 [ghost91-](https://github.com/ghost91-)
* fix(types): fix "near" aggregation operator input type #12954 [Jokero](https://github.com/Jokero)
* fix(types): add missing Top operator to AccumulatorOperator type declaration #12952 [lpizzinidev](https://github.com/lpizzinidev)
Expand Down Expand Up @@ -675,7 +679,7 @@
* docs(typescript): add notes about virtual context to Mongoose 6 migration and TypeScript virtuals docs #12912 #12806
* docs(schematypes): removed dead link and fixed formatting #12897 #12885 [lpizzinidev](https://github.com/lpizzinidev)
* docs: fix link to lean api #12910 [manniL](https://github.com/manniL)
* docs: list all possible strings for schema.pre in one place #12868
* docs: list all possible strings for schema.pre in one place #12868
* docs: add list of known incompatible npm packages #12892 [IslandRhythms](https://github.com/IslandRhythms)

6.8.3 / 2023-01-06
Expand Down
41 changes: 23 additions & 18 deletions lib/helpers/populate/getModelsMapForPopulate.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
if (hasMatchFunction) {
match = match.call(doc, doc);
}
if (Array.isArray(match)) {
for (const item of match) {
if (item != null && item.$where) {
throw new MongooseError('Cannot use $where filter with populate() match');
}
}
} else if (match != null && match.$where != null) {
throw new MongooseError('Cannot use $where filter with populate() match');
}
throwOn$where(match);
data.match = match;
data.hasMatchFunction = hasMatchFunction;
data.isRefPath = isRefPath;
Expand Down Expand Up @@ -470,15 +462,7 @@ function _virtualPopulate(model, docs, options, _virtualRes) {
data.match = match;
data.hasMatchFunction = hasMatchFunction;

if (Array.isArray(match)) {
for (const item of match) {
if (item != null && item.$where) {
throw new MongooseError('Cannot use $where filter with populate() match');
}
}
} else if (match != null && match.$where != null) {
throw new MongooseError('Cannot use $where filter with populate() match');
}
throwOn$where(match);

// Get local fields
const ret = _getLocalFieldValues(doc, localField, model, options, virtual);
Expand Down Expand Up @@ -751,3 +735,24 @@ function _findRefPathForDiscriminators(doc, modelSchema, data, options, normaliz

return modelNames;
}

/**
* Throw an error if there are any $where keys
*/

function throwOn$where(match) {
if (match == null) {
return;
}
if (typeof match !== 'object') {
return;
}
for (const key of Object.keys(match)) {
if (key === '$where') {
throw new MongooseError('Cannot use $where filter with populate() match');
}
if (match[key] != null && typeof match[key] === 'object') {
throwOn$where(match[key]);
}
}
}
21 changes: 17 additions & 4 deletions test/model.populate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3582,21 +3582,34 @@ describe('model: populate:', function() {
const parent = await Parent.create({ name: 'Anakin', child: child._id });

await assert.rejects(
() => Parent.findOne().populate({ path: 'child', match: { $where: 'console.log("oops!");' } }),
() => Parent.findOne().populate({ path: 'child', match: () => ({ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }) }),
/Cannot use \$where filter with populate\(\) match/
);
await assert.rejects(
() => Parent.find().populate({ path: 'child', match: { $where: 'console.log("oops!");' } }),
() => Parent.find().populate({ path: 'child', match: () => ({ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }) }),
/Cannot use \$where filter with populate\(\) match/
);
await assert.rejects(
() => parent.populate({ path: 'child', match: { $where: 'console.log("oops!");' } }),
() => parent.populate({ path: 'child', match: () => ({ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }) }),
/Cannot use \$where filter with populate\(\) match/
);
await assert.rejects(
() => Child.find().populate({ path: 'parent', match: { $where: 'console.log("oops!");' } }),
() => Child.find().populate({ path: 'parent', match: () => ({ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }) }),
/Cannot use \$where filter with populate\(\) match/
);
await assert.rejects(
() => Child.find().populate({ path: 'parent', match: () => ({ $or: [{ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }] }) }),
/Cannot use \$where filter with populate\(\) match/
);
await assert.rejects(
() => Child.find().populate({ path: 'parent', match: () => ({ $and: [{ $where: 'typeof console !== "undefined" ? doesNotExist("foo") : true;' }] }) }),
/Cannot use \$where filter with populate\(\) match/
);

class MyClass {}
MyClass.prototype.$where = 'typeof console !== "undefined" ? doesNotExist("foo") : true;';
// OK because sift only looks through own properties
await Child.find().populate({ path: 'parent', match: () => new MyClass() });
});

it('multiple source docs', async function() {
Expand Down

0 comments on commit 4fe9a90

Please sign in to comment.