Skip to content

Commit

Permalink
fix(schema): correctly handle uuids with populate()
Browse files Browse the repository at this point in the history
Fix #13267
  • Loading branch information
vkarpov15 committed Apr 23, 2023
1 parent bc69fc8 commit 4332472
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 10 deletions.
18 changes: 10 additions & 8 deletions lib/schema/uuid.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const MongooseBuffer = require('../types/buffer');
const SchemaType = require('../schematype');
const CastError = SchemaType.CastError;
const utils = require('../utils');
const isBsonType = require('../helpers/isBsonType');
const handleBitwiseOperator = require('./operators/bitwise');

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;
Expand Down Expand Up @@ -86,7 +85,13 @@ function binaryToString(uuidBin) {

function SchemaUUID(key, options) {
SchemaType.call(this, key, options, 'UUID');
this.getters.push(binaryToString);
this.getters.push(function(value) {
// For populated
if (value != null && value.$__ != null) {
return value;
}
return binaryToString(value);
});
}

/**
Expand All @@ -110,7 +115,7 @@ SchemaUUID.prototype.constructor = SchemaUUID;
*/

SchemaUUID._cast = function(value) {
if (value === null) {
if (value == null) {
return value;
}

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

SchemaUUID.prototype.cast = function(value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
if (isBsonType(value, 'UUID')) {
return value;
}

if (utils.isNonBuiltinObject(value) &&
SchemaType._isRef(this, value, doc, init)) {
return this._castRef(value, doc, init);
}

Expand Down
1 change: 1 addition & 0 deletions lib/schematype.js
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,7 @@ SchemaType.prototype._castRef = function _castRef(value, doc, init) {
const path = doc.$__fullPath(this.path, true);
const owner = doc.ownerDocument();
const pop = owner.$populated(path, true);

let ret = value;
if (!doc.$__.populated ||
!doc.$__.populated[path] ||
Expand Down
2 changes: 2 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Module dependencies.
*/

const UUID = require('bson').UUID;
const ms = require('ms');
const mpath = require('mpath');
const ObjectId = require('./types/objectid');
Expand Down Expand Up @@ -395,6 +396,7 @@ exports.isNonBuiltinObject = function isNonBuiltinObject(val) {
return typeof val === 'object' &&
!exports.isNativeObject(val) &&
!exports.isMongooseType(val) &&
!(val instanceof UUID) &&
val != null;
};

Expand Down
24 changes: 22 additions & 2 deletions test/schema.uuid.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
const start = require('./common');
const util = require('./util');

const bson = require('bson');

const assert = require('assert');
const bson = require('bson');
const { randomUUID } = require('crypto');

const mongoose = start.mongoose;
const Schema = mongoose.Schema;
Expand Down Expand Up @@ -129,6 +129,26 @@ describe('SchemaUUID', function() {
assert.equal(organization, undefined);
});

it('works with populate (gh-13267)', async function() {
const userSchema = new mongoose.Schema({
_id: { type: 'UUID', default: () => randomUUID() },
name: String,
createdBy: {
type: 'UUID',
ref: 'User'
}
});
const User = db.model('User', userSchema);

const u1 = await User.create({ name: 'admin' });
const { _id } = await User.create({ name: 'created', createdBy: u1._id });

const pop = await User.findById(_id).populate('createdBy');
assert.equal(pop.createdBy.name, 'admin');

await pop.save();
});

// the following are TODOs based on SchemaUUID.prototype.$conditionalHandlers which are not tested yet
it('should work with $bits* operators');
it('should work with $all operator');
Expand Down

0 comments on commit 4332472

Please sign in to comment.