Mongoose encryption middleware doesn't call after aggregation
As I didn't find a better answer, I changed my code (as workaround unfortunately) to decrypt the object by myself -using the code of mongoose-encryption to decrypt after the aggregation has finished.
Most of the code was taken from GitHub (called decryptOne in my code): decryptSync function of mongoose-encryption
The 'tricky' thing was to decrypt the inner lookup value - the inner document also has the "_ct" field that should be decrypted.
let lookup: { [innerField: string]: string[]; } = { user: ['bio'] };this.decryptAggregation(aggregationResult, lookup);
My function gets a dictionary of the known lookup collection and its wanted fields after decryption. In that example, the other collection named users and its encrypted field is just his bio.
decryptAggregation(res: any[], innerLookup: { [innerField: string]: string[]; }) { for (let doc of res) { this.decryptSync(doc, innerLookup); }}private decryptSync(doc: any, innerLookup: { [innerField: string]: string[]; }) { this.decryptOne(doc, this.encryptedFields); for (let innerObj in innerLookup) { if (innerLookup.hasOwnProperty(innerObj)) { this.decryptOne(doc[innerObj], innerLookup[innerObj]); } }};private decryptOne(doc: any, fields: string[]) { let ct, ctWithIV, decipher, iv, idString, decryptedObject, decryptedObjectJSON, decipheredVal; if (doc._ct) { ctWithIV = doc._ct.hasOwnProperty('buffer') ? doc._ct.buffer : doc._ct; iv = ctWithIV.slice(this.VERSION_LENGTH, this.VERSION_LENGTH + this.IV_LENGTH); ct = ctWithIV.slice(this.VERSION_LENGTH + this.IV_LENGTH, ctWithIV.length); decipher = crypto.createDecipheriv(this.ENCRYPTION_ALGORITHM, this.encryptionKey, iv); try { decryptedObjectJSON = decipher.update(ct, undefined, 'utf8') + decipher.final('utf8'); decryptedObject = JSON.parse(decryptedObjectJSON); } catch (err) { if (doc._id) { idString = doc._id.toString(); } else { idString = 'unknown'; } throw new Error('Error parsing JSON during decrypt of ' + idString + ': ' + err); } fields.forEach((field) => { decipheredVal = mpath.get(field, decryptedObject); //JSON.parse returns {type: "Buffer", data: Buffer} for Buffers //https://nodejs.org/api/buffer.html#buffer_buf_tojson if (_.isObject(decipheredVal) && decipheredVal.type === "Buffer") { this.setFieldValue(doc, field, decipheredVal.data); } else { this.setFieldValue(doc, field, decipheredVal); } }); doc._ct = undefined; doc._ac = undefined; }}
After those function I got my wanted object fully decrypted, the last thing to do was to project the wanted fields back to the client - with lodash.pick