From 4757bcdc53fa11af658d1c9acbdbb6292f055618 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 1 Oct 2024 21:19:34 -0400 Subject: [PATCH] fix: handle buffers stored in MongoDB as EJSON representation with { $binary } Fix #14911 --- lib/schema/buffer.js | 8 ++++++++ test/document.test.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/lib/schema/buffer.js b/lib/schema/buffer.js index 6444ebd8835..e5cec2e0158 100644 --- a/lib/schema/buffer.js +++ b/lib/schema/buffer.js @@ -219,6 +219,14 @@ SchemaBuffer.prototype.cast = function(value, doc, init) { return ret; } + if (utils.isPOJO(value) && (value.$binary instanceof Binary || typeof value.$binary === 'string')) { + const buf = this.cast(Buffer.from(value.$binary, 'base64')); + if (value.$type != null) { + buf._subtype = value.$type; + return buf; + } + } + throw new CastError('Buffer', value, this.path, null, this); }; diff --git a/test/document.test.js b/test/document.test.js index 7150ffe64b4..d3c3f4a86ff 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -13926,6 +13926,35 @@ describe('document', function() { cur.subdocs[0] = { test: 'updated' }; await savedDoc.save(); }); + + it('handles buffers stored as EJSON POJO (gh-14911)', async function() { + const pdfSchema = new mongoose.Schema({ + pdfSettings: { + type: { + _id: false, + fileContent: { type: Buffer, required: true }, + filePreview: { type: Buffer, required: true }, + fileName: { type: String, required: true } + } + } + }); + const PdfModel = db.model('Test', pdfSchema); + + const _id = new mongoose.Types.ObjectId(); + const buf = { $binary: Buffer.from('hello', 'utf8').toString('base64'), $type: '00' }; + await PdfModel.collection.insertOne({ + _id, + pdfSettings: { + fileContent: buf, + filePreview: buf, + fileName: 'sample.pdf' + } + }); + + const reloaded = await PdfModel.findById(_id); + assert.ok(Buffer.isBuffer(reloaded.pdfSettings.fileContent)); + assert.strictEqual(reloaded.pdfSettings.fileContent.toString('utf8'), 'hello'); + }); }); describe('Check if instance function that is supplied in schema option is available', function() {