From 0d4f0cb521d144b0471a7695eb29beb788313faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Y=C3=A1=C3=B1ez=20Parareda?= Date: Tue, 23 Oct 2018 09:23:27 +0200 Subject: [PATCH 1/2] Check if the field exists before decryption Sometimes the field could be marked to not be retrieved, in that case, the decrypt function will fail because because the field is undefined. --- lib/mongoose-field-encryption.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/mongoose-field-encryption.js b/lib/mongoose-field-encryption.js index d93f511..d7f1961 100644 --- a/lib/mongoose-field-encryption.js +++ b/lib/mongoose-field-encryption.js @@ -138,11 +138,13 @@ const fieldEncryption = function(schema, options) { obj[encryptedFieldName] = false; obj[encryptedFieldData] = ""; } else { + // If the field has been marked to not be retrieved, it'll be undefined + if (obj[field]) { // handle strings separately to maintain searchability - const encryptedValue = obj[field]; - - obj[field] = decrypt(encryptedValue, secret); - obj[encryptedFieldName] = false; + const encryptedValue = obj[field]; + obj[field] = decrypt(encryptedValue, secret); + obj[encryptedFieldName] = false; + } } } } From 5cbe372ae3d204199d48331d7e6b1c52095515bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Y=C3=A1=C3=B1ez=20Parareda?= Date: Wed, 24 Oct 2018 16:25:29 +0200 Subject: [PATCH 2/2] Unit test for the issue that crashed when some fields were not retrieved by default --- test/test-db.js | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/test/test-db.js b/test/test-db.js index 1c3827e..375a51d 100644 --- a/test/test-db.js +++ b/test/test-db.js @@ -16,6 +16,7 @@ describe("mongoose-field-encryption plugin db", function() { let NestedFieldEncryptionSchema = new mongoose.Schema({ toEncryptString: { type: String, required: true }, + toEncryptStringNotRetrieved: { type: String, select: false }, toEncryptObject: { nested: String }, @@ -24,7 +25,7 @@ describe("mongoose-field-encryption plugin db", function() { }); NestedFieldEncryptionSchema.plugin(fieldEncryptionPlugin, { - fields: ["toEncryptString", "toEncryptObject", "toEncryptArray", "toEncryptDate"], + fields: ["toEncryptString", "toEncryptObject", "toEncryptArray", "toEncryptDate", "toEncryptStringNotRetrieved"], secret: "icanhazcheezburger" // should ideally be process.env.SECRET }); @@ -290,6 +291,7 @@ describe("mongoose-field-encryption plugin db", function() { _id: sut._id }, { + toEncryptString: "yaddayadda", toEncryptObject: { nested: "snoop" } } ); @@ -299,6 +301,7 @@ describe("mongoose-field-encryption plugin db", function() { }) .then(foundArray => { const found = foundArray[0]; + expect(found.toEncryptString).to.eql("yaddayadda"); expect(found.toEncryptObject.nested).to.eql("snoop"); }); }); @@ -332,4 +335,35 @@ describe("mongoose-field-encryption plugin db", function() { expect(found.toEncryptString).to.eql("already encrypted string"); }); }) + + it("should decrypt data on find() method call even if some fields are marked as not selectables", () => { + // given + let sut = getSut(); + + // when + return sut + .save() + .then(() => { + expectEncryptionValues(sut); + + return NestedFieldEncryption.findOneAndUpdate( + { + _id: sut._id + }, + { + toEncryptString: "yaddayadda", + toEncryptObject: { nested: "snoop" }, + toEncryptStringNotRetrieved: "dubidubida" + } + ); + }) + .then(() => { + return NestedFieldEncryption.find({ _id: sut._id }); + }) + .then(foundArray => { + const found = foundArray[0]; + expect(found.toEncryptString).to.equal("yaddayadda"); + expect(found.toEncryptStringNotRetrieved).to.be.undefined; + }); + }); });