Skip to content

Commit 9616af7

Browse files
committedJul 11, 2023
fix(schema): correctly handle uuids with populate()
Backport #13317 Fix #13595
1 parent 305ce4f commit 9616af7

File tree

4 files changed

+36
-10
lines changed

4 files changed

+36
-10
lines changed
 

‎lib/schema/uuid.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ const MongooseBuffer = require('../types/buffer');
88
const SchemaType = require('../schematype');
99
const CastError = SchemaType.CastError;
1010
const utils = require('../utils');
11-
const isBsonType = require('../helpers/isBsonType');
1211
const handleBitwiseOperator = require('./operators/bitwise');
1312

1413
const UUID_FORMAT = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;
@@ -86,7 +85,13 @@ function binaryToString(uuidBin) {
8685

8786
function SchemaUUID(key, options) {
8887
SchemaType.call(this, key, options, 'UUID');
89-
this.getters.push(binaryToString);
88+
this.getters.push(function(value) {
89+
// For populated
90+
if (value != null && value.$__ != null) {
91+
return value;
92+
}
93+
return binaryToString(value);
94+
});
9095
}
9196

9297
/**
@@ -110,7 +115,7 @@ SchemaUUID.prototype.constructor = SchemaUUID;
110115
*/
111116

112117
SchemaUUID._cast = function(value) {
113-
if (value === null) {
118+
if (value == null) {
114119
return value;
115120
}
116121

@@ -247,11 +252,8 @@ SchemaUUID.prototype.checkRequired = function checkRequired(value) {
247252
*/
248253

249254
SchemaUUID.prototype.cast = function(value, doc, init) {
250-
if (SchemaType._isRef(this, value, doc, init)) {
251-
if (isBsonType(value, 'UUID')) {
252-
return value;
253-
}
254-
255+
if (utils.isNonBuiltinObject(value) &&
256+
SchemaType._isRef(this, value, doc, init)) {
255257
return this._castRef(value, doc, init);
256258
}
257259

‎lib/schematype.js

+1
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,7 @@ SchemaType.prototype._castRef = function _castRef(value, doc, init) {
15211521
const path = doc.$__fullPath(this.path, true);
15221522
const owner = doc.ownerDocument();
15231523
const pop = owner.$populated(path, true);
1524+
15241525
let ret = value;
15251526
if (!doc.$__.populated ||
15261527
!doc.$__.populated[path] ||

‎lib/utils.js

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Module dependencies.
55
*/
66

7+
const UUID = require('bson').UUID;
78
const ms = require('ms');
89
const mpath = require('mpath');
910
const ObjectId = require('./types/objectid');
@@ -406,6 +407,7 @@ exports.isNonBuiltinObject = function isNonBuiltinObject(val) {
406407
return typeof val === 'object' &&
407408
!exports.isNativeObject(val) &&
408409
!exports.isMongooseType(val) &&
410+
!(val instanceof UUID) &&
409411
val != null;
410412
};
411413

‎test/schema.uuid.test.js

+23-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
const start = require('./common');
44
const util = require('./util');
55

6-
const bson = require('bson');
7-
86
const assert = require('assert');
7+
const bson = require('bson');
8+
const { randomUUID } = require('crypto');
99

1010
const mongoose = start.mongoose;
1111
const Schema = mongoose.Schema;
@@ -129,6 +129,27 @@ describe('SchemaUUID', function() {
129129
assert.equal(organization, undefined);
130130
});
131131

132+
it('works with populate (gh-13267)', async function() {
133+
const userSchema = new mongoose.Schema({
134+
_id: { type: 'UUID', default: () => randomUUID() },
135+
name: String,
136+
createdBy: {
137+
type: 'UUID',
138+
ref: 'User'
139+
}
140+
});
141+
const User = db.model('User', userSchema);
142+
143+
const u1 = await User.create({ name: 'admin' });
144+
const { _id } = await User.create({ name: 'created', createdBy: u1._id });
145+
146+
const pop = await User.findById(_id).populate('createdBy').orFail();
147+
assert.equal(pop.createdBy.name, 'admin');
148+
assert.equal(pop.createdBy._id.toString(), u1._id.toString());
149+
150+
await pop.save();
151+
});
152+
132153
// the following are TODOs based on SchemaUUID.prototype.$conditionalHandlers which are not tested yet
133154
it('should work with $bits* operators');
134155
it('should work with $all operator');

0 commit comments

Comments
 (0)
Please sign in to comment.