Skip to content

Commit 35d6c70

Browse files
committed
fix(bulkWrite): pass overwriteImmutable option to castUpdate fixes
Fix #15781 Backport #15782 to 7.x
1 parent 15e7743 commit 35d6c70

File tree

4 files changed

+47
-7
lines changed

4 files changed

+47
-7
lines changed

lib/helpers/model/castBulkWrite.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ module.exports = function castBulkWrite(originalModel, op, options) {
6969
if (model.schema.$timestamps != null && op['updateOne'].timestamps !== false) {
7070
const createdAt = model.schema.$timestamps.createdAt;
7171
const updatedAt = model.schema.$timestamps.updatedAt;
72-
applyTimestampsToUpdate(now, createdAt, updatedAt, op['updateOne']['update'], {});
72+
applyTimestampsToUpdate(now, createdAt, updatedAt, op['updateOne']['update'], {
73+
timestamps: op['updateOne'].timestamps
74+
});
7375
}
7476

7577
if (op['updateOne'].timestamps !== false) {
@@ -100,7 +102,8 @@ module.exports = function castBulkWrite(originalModel, op, options) {
100102
op['updateOne']['update'] = castUpdate(model.schema, op['updateOne']['update'], {
101103
strict: strict,
102104
overwrite: false,
103-
upsert: op['updateOne'].upsert
105+
upsert: op['updateOne'].upsert,
106+
overwriteImmutable: op['updateOne'].overwriteImmutable
104107
}, model, op['updateOne']['filter']);
105108
} catch (error) {
106109
return callback(error, null);
@@ -136,7 +139,9 @@ module.exports = function castBulkWrite(originalModel, op, options) {
136139
if (model.schema.$timestamps != null && op['updateMany'].timestamps !== false) {
137140
const createdAt = model.schema.$timestamps.createdAt;
138141
const updatedAt = model.schema.$timestamps.updatedAt;
139-
applyTimestampsToUpdate(now, createdAt, updatedAt, op['updateMany']['update'], {});
142+
applyTimestampsToUpdate(now, createdAt, updatedAt, op['updateMany']['update'], {
143+
timestamps: op['updateMany'].timestamps
144+
});
140145
}
141146
if (op['updateMany'].timestamps !== false) {
142147
applyTimestampsToChildren(now, op['updateMany']['update'], model.schema);
@@ -158,7 +163,8 @@ module.exports = function castBulkWrite(originalModel, op, options) {
158163
op['updateMany']['update'] = castUpdate(model.schema, op['updateMany']['update'], {
159164
strict: strict,
160165
overwrite: false,
161-
upsert: op['updateMany'].upsert
166+
upsert: op['updateMany'].upsert,
167+
overwriteImmutable: op['updateMany'].overwriteImmutable
162168
}, model, op['updateMany']['filter']);
163169
} catch (error) {
164170
return callback(error, null);

lib/helpers/query/castUpdate.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
240240

241241
if (op !== '$setOnInsert' &&
242242
!options.overwrite &&
243-
handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
243+
handleImmutable(schematype, strict, obj, key, prefix + key, options, context)) {
244244
continue;
245245
}
246246

@@ -335,7 +335,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
335335
// You can use `$setOnInsert` with immutable keys
336336
if (op !== '$setOnInsert' &&
337337
!options.overwrite &&
338-
handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
338+
handleImmutable(schematype, strict, obj, key, prefix + key, options, context)) {
339339
continue;
340340
}
341341

lib/helpers/query/handleImmutable.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const StrictModeError = require('../../error/strict');
44

5-
module.exports = function handleImmutable(schematype, strict, obj, key, fullPath, ctx) {
5+
module.exports = function handleImmutable(schematype, strict, obj, key, fullPath, options, ctx) {
66
if (schematype == null || !schematype.options || !schematype.options.immutable) {
77
return false;
88
}
@@ -15,6 +15,10 @@ module.exports = function handleImmutable(schematype, strict, obj, key, fullPath
1515
return false;
1616
}
1717

18+
if (options && options.overwriteImmutable) {
19+
return false;
20+
}
21+
1822
if (strict === false) {
1923
return false;
2024
}

test/model.updateOne.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2707,6 +2707,36 @@ describe('model: updateOne: ', function() {
27072707
assert.equal(doc.age, 20);
27082708
});
27092709

2710+
it('overwriting immutable createdAt with bulkWrite (gh-15781)', async function() {
2711+
const start = new Date().valueOf();
2712+
const schema = Schema({
2713+
createdAt: {
2714+
type: mongoose.Schema.Types.Date,
2715+
immutable: true
2716+
},
2717+
name: String
2718+
}, { timestamps: true });
2719+
2720+
const Model = db.model('Test', schema);
2721+
2722+
await Model.create({ name: 'gh-15781' });
2723+
let doc = await Model.collection.findOne({ name: 'gh-15781' });
2724+
assert.ok(doc.createdAt.valueOf() >= start);
2725+
2726+
const createdAt = new Date('2011-06-01');
2727+
assert.ok(createdAt.valueOf() < start.valueOf());
2728+
await Model.bulkWrite([{
2729+
updateOne: {
2730+
filter: { _id: doc._id },
2731+
update: { name: 'gh-15781 update', createdAt },
2732+
overwriteImmutable: true,
2733+
timestamps: false
2734+
}
2735+
}]);
2736+
doc = await Model.collection.findOne({ name: 'gh-15781 update' });
2737+
assert.equal(doc.createdAt.valueOf(), createdAt.valueOf());
2738+
});
2739+
27102740
it('updates buffers with `runValidators` successfully (gh-8580)', async function() {
27112741
const Test = db.model('Test', Schema({
27122742
data: { type: Buffer, required: true }

0 commit comments

Comments
 (0)