Skip to content

Commit

Permalink
Fix errors with encrypted subdoc arrays on Mongoose v6
Browse files Browse the repository at this point in the history
As of Mongoose v6, encrypted subdocument arrays lead to the following
error when updating an existing document:

> MongoServerError: Updating the path '…' would create a conflict at '…'

This change circumvents the problem by marking the corresponding schema
paths as unmodified (which should be safe, since those encrypted fields
are not meant to be stored anyway).

Fixes joegoldbeck#105
  • Loading branch information
Markus Dolic committed Aug 12, 2022
1 parent c3dd81a commit 6400629
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/plugins/mongoose-encryption.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ var mongooseEncryption = function(schema, options) {
// remove encrypted fields from cleartext
encryptedFields.forEach(function(field){
setFieldValue(that, field, undefined);
// prevent conflict errors due to array change tracking in Mongoose 6
if (that.schema.paths[field].$isMongooseArray) {
that.unmarkModified(field);
}
});

cb(null);
Expand Down
42 changes: 42 additions & 0 deletions test/encrypt.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,48 @@ describe 'Array EmbeddedDocument', ->
done()
return

describe 'when entire children array is encrypted', ->
before ->
ChildModelSchema = mongoose.Schema
text: type: String

ParentModelSchema = mongoose.Schema
children: [ChildModelSchema]

ParentModelSchema.plugin encrypt,
encryptionKey: encryptionKey,
signingKey: signingKey
encryptedFields: ['children']

@ParentModel = mongoose.model 'EncChildrenArrayParent', ParentModelSchema
@ChildModel = mongoose.model 'EncChildrenArrayChild', ChildModelSchema

beforeEach (done) ->
@parentDoc = new @ParentModel

childDoc = new @ChildModel
text: 'Child unencrypted text'

@parentDoc.children.addToSet childDoc

@parentDoc.save done

after (done) ->
@parentDoc.remove done

describe 'document.save()', ->
it 'should save changes to encrypted children', (done) ->
@ParentModel.findById @parentDoc._id, (err, doc) =>
assert.equal err, null
doc.children[0].text = 'New unencrypted text'
doc.save (err) =>
assert.equal err, null
@ParentModel.findById doc._id, (err, updatedDoc) ->
assert.equal err, null
assert.equal updatedDoc.children[0].text, 'New unencrypted text'
done()
return

describe 'when child and parent are encrypted', ->
before ->
ChildModelSchema = mongoose.Schema
Expand Down

0 comments on commit 6400629

Please sign in to comment.