Skip to content

Commit

Permalink
Merge branch 'Automattic:master' into feature/model-schema-type
Browse files Browse the repository at this point in the history
  • Loading branch information
emiljanitzek committed Jul 22, 2022
2 parents dd0dd96 + d2d0c01 commit 3e2ae76
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 26 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Expand Up @@ -41,7 +41,7 @@ test/files/main.js

package-lock.json

.config*
.config.js

# Compiled docs
docs/*.html
Expand All @@ -50,6 +50,9 @@ docs/typescript/*.html
docs/api/*.html
index.html

# Local Netlify folder
.netlify

# yarn package-lock
yarn.lock

Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,10 @@
6.4.6 / 2022-07-20
==================
* fix(schema): disallow setting __proto__ when creating schema with dotted properties #12085
* fix(document): avoid mutating original object passed to $set() when applying defaults to nested properties #12102
* fix(query): apply lean transform option to top-level document #12093
* docs(migrating_to_6): correct example for `isObjectIdOrHexString()` #12123 [LokeshKanumoori](https://github.com/LokeshKanumoori)

6.4.5 / 2022-07-18
==================
* fix(model+timestamps): set timestamps on subdocuments in insertMany() #12060
Expand Down
4 changes: 2 additions & 2 deletions docs/migrating_to_6.md
Expand Up @@ -194,8 +194,8 @@ mongoose.isValidObjectId(new User({ name: 'test' })); // true
// character hex strings.
mongoose.isObjectIdOrHexString(new mongoose.Types.ObjectId()); // true
mongoose.isObjectIdOrHexString('62261a65d66c6be0a63c051f'); // true
mongoose.isValidObjectId('0123456789ab'); // false
mongoose.isValidObjectId(6); // false
mongoose.isObjectIdOrHexString('0123456789ab'); // false
mongoose.isObjectIdOrHexString(6); // false
```

<h3 id="schema-defined-document-key-order"><a href="#schema-defined-document-key-order">Schema Defined Document Key Order</a></h3>
Expand Down
2 changes: 1 addition & 1 deletion lib/document.js
Expand Up @@ -1149,8 +1149,8 @@ Document.prototype.$set = function $set(path, val, type, options) {
}

if (utils.isNonBuiltinObject(valForKey) && pathtype === 'nested') {
$applyDefaultsToNested(path[key], prefix + key, this);
this.$set(prefix + key, path[key], constructing, Object.assign({}, options, { _skipMarkModified: true }));
$applyDefaultsToNested(this.$get(prefix + key), prefix + key, this);
continue;
} else if (strict) {
// Don't overwrite defaults with undefined keys (gh-3981) (gh-9039)
Expand Down
10 changes: 8 additions & 2 deletions lib/query.js
Expand Up @@ -4019,7 +4019,9 @@ Query.prototype._findAndModify = function(type, callback) {
*/

function _completeOneLean(schema, doc, path, res, opts, callback) {
if (opts.lean && opts.lean.transform) {
if (opts.lean && typeof opts.lean.transform === 'function') {
opts.lean.transform(doc);

for (let i = 0; i < schema.childSchemas.length; i++) {
const childPath = path ? path + '.' + schema.childSchemas[i].model.path : schema.childSchemas[i].model.path;
const _schema = schema.childSchemas[i].schema;
Expand Down Expand Up @@ -4053,7 +4055,11 @@ function _completeOneLean(schema, doc, path, res, opts, callback) {
*/

function _completeManyLean(schema, docs, path, opts, callback) {
if (opts.lean && opts.lean.transform) {
if (opts.lean && typeof opts.lean.transform === 'function') {
for (const doc of docs) {
opts.lean.transform(doc);
}

for (let i = 0; i < schema.childSchemas.length; i++) {
const childPath = path ? path + '.' + schema.childSchemas[i].model.path : schema.childSchemas[i].model.path;
const _schema = schema.childSchemas[i].schema;
Expand Down
7 changes: 7 additions & 0 deletions lib/schema.js
Expand Up @@ -554,6 +554,10 @@ Schema.prototype.add = function add(obj, prefix) {
const keys = Object.keys(obj);
const typeKey = this.options.typeKey;
for (const key of keys) {
if (utils.specialProperties.has(key)) {
continue;
}

const fullPath = prefix + key;
const val = obj[key];

Expand Down Expand Up @@ -854,6 +858,9 @@ Schema.prototype.path = function(path, obj) {
let fullPath = '';

for (const sub of subpaths) {
if (utils.specialProperties.has(sub)) {
throw new Error('Cannot set special property `' + sub + '` on a schema');
}
fullPath = fullPath += (fullPath.length > 0 ? '.' : '') + sub;
if (!branch[sub]) {
this.nested[fullPath] = true;
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{
"name": "mongoose",
"description": "Mongoose MongoDB ODM",
"version": "6.4.5",
"version": "6.4.6",
"author": "Guillermo Rauch <guillermo@learnboost.com>",
"keywords": [
"mongodb",
Expand Down
8 changes: 5 additions & 3 deletions test/document.test.js
Expand Up @@ -8831,7 +8831,7 @@ describe('document', function() {
assert.ok(!user.updatedAt);
});

it('Sets default when passing undefined as value for a key in a nested subdoc (gh-9039)', async function() {
it('Sets default when passing undefined as value for a key in a nested subdoc (gh-12102) (gh-9039)', async function() {
const Test = db.model('Test', {
nested: {
prop: {
Expand All @@ -8841,9 +8841,11 @@ describe('document', function() {
}
});


const doc = await Test.create({ nested: { prop: undefined } });
const obj = { nested: { prop: undefined } };
const doc = await Test.create(obj);
assert.equal(doc.nested.prop, 'some default value');

assert.deepStrictEqual(obj, { nested: { prop: undefined } });
});

it('allows accessing $locals when initializing (gh-9098)', function() {
Expand Down
38 changes: 22 additions & 16 deletions test/query.test.js
Expand Up @@ -4006,22 +4006,28 @@ describe('Query', function() {
});
const Test = db.model('gh10423', testSchema);
await Test.create({ name: 'foo', foo: [{ sub: 'Test' }, { sub: 'Testerson' }], otherName: { nickName: 'Bar' } });
const result = await Test.find().lean({ transform: (doc) => {
delete doc._id;
return doc;
} });
assert(result[0]._id);
assert.equal(result[0].otherName._id, undefined);
assert.equal(result[0].foo[0]._id, undefined);
assert.equal(result[0].foo[1]._id, undefined);
const single = await Test.findOne().lean({ transform: (doc) => {
delete doc._id;
return doc;
} });
assert(single._id);
assert.equal(single.otherName._id, undefined);
assert.equal(single.foo[0]._id, undefined);
assert.equal(single.foo[0]._id, undefined);

const result = await Test.find().lean({
transform: (doc) => {
delete doc._id;
return doc;
}
});
assert.strictEqual(result[0]._id, undefined);
assert.strictEqual(result[0].otherName._id, undefined);
assert.strictEqual(result[0].foo[0]._id, undefined);
assert.strictEqual(result[0].foo[1]._id, undefined);

const single = await Test.findOne().lean({
transform: (doc) => {
delete doc._id;
return doc;
}
});
assert.strictEqual(single._id, undefined);
assert.strictEqual(single.otherName._id, undefined);
assert.strictEqual(single.foo[0]._id, undefined);
assert.strictEqual(single.foo[0]._id, undefined);
});

it('skips applying default projections over slice projections (gh-11940)', async function() {
Expand Down
23 changes: 23 additions & 0 deletions test/schema.test.js
Expand Up @@ -924,6 +924,19 @@ describe('schema', function() {

assert.equal(called, true);
});

it('options param (gh-12077)', function() {
const Tobi = new Schema();
let called = false;

Tobi.plugin(function(schema, opts) {
assert.equal(schema, Tobi);
assert.deepStrictEqual(opts, { answer: 42 });
called = true;
}, { answer: 42 });

assert.equal(called, true);
});
});

describe('options', function() {
Expand Down Expand Up @@ -2792,4 +2805,14 @@ describe('schema', function() {
});
}, /Cannot use schema-level projections.*subdocument_mapping.not_selected/);
});

it('disallows setting special properties with `add()` or constructor (gh-12085)', async function() {
const maliciousPayload = '{"__proto__.toString": "Number"}';

assert.throws(() => {
mongoose.Schema(JSON.parse(maliciousPayload));
}, /__proto__/);

assert.ok({}.toString());
});
});

0 comments on commit 3e2ae76

Please sign in to comment.