From 9836d99e0f194490a0865e4d2cd233d35e58ac31 Mon Sep 17 00:00:00 2001 From: Hage Yaapa Date: Thu, 9 May 2019 10:07:16 +0530 Subject: [PATCH] feat: add mongodb.dataType to property options Adds mongodb.dataType to model property options --- lib/mongodb.js | 13 +++- test/id.test.js | 179 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 1 deletion(-) diff --git a/lib/mongodb.js b/lib/mongodb.js index 93e01add3..2a30df6bc 100644 --- a/lib/mongodb.js +++ b/lib/mongodb.js @@ -1881,14 +1881,25 @@ MongoDB.prototype.isObjectIDProperty = function(model, prop, value, options) { ) { return true; } else if ('string' === typeof value) { + // values doesn't look like an ObjectID + if (!value.match(/^[0-9a-fA-F]{24}$/)) return false; + + // value looks like an ObjectID, and it should be treated as one + // because `prop.mongodb.dataType` is set to 'ObjectID' + // this condition overrides the `strictObjectIDCoercion` setting + if (prop.id && prop.mongodb && prop.mongodb.dataType === 'ObjectID') return true; + + // value looks like an ObjectID, determine its nature based on `strictObjectIDCoercion` var settings = this._models[model] && this._models[model].settings; + options = options || {}; var strict = (settings && settings.strictObjectIDCoercion) || this.settings.strictObjectIDCoercion || options.strictObjectIDCoercion; + if (strict) return false; // unless explicitly typed, don't coerce - return /^[0-9a-fA-F]{24}$/.test(value); + else return true; } else { return false; } diff --git a/test/id.test.js b/test/id.test.js index 6b7ffd2cf..35df36f0b 100644 --- a/test/id.test.js +++ b/test/id.test.js @@ -247,3 +247,182 @@ describe('mongodb default id name', function() { ); }); }); + +describe('strictObjectIDCoercion', function() { + var ObjectID = ds.connector.getDefaultIdType(); + var objectIdLikeString = '7cd2ad46ffc580ba45d3cb1f'; + + context('set to false (default)', function() { + var User = ds.createModel( + 'user1', + { + id: {type: String, id: true}, + name: String, + } + ); + + beforeEach(function(done) { + User.deleteAll(done); + }); + + it('should find model with ObjectID id', function(done) { + User.create({name: 'John'}, function(err, user) { + user.id.should.be.an.instanceOf(ds.ObjectID); + User.findById(user.id, function(err, user) { + user.should.not.be.null(); + done(err, user); + }); + }); + }); + + it('should find model with ObjectID-like id', function(done) { + User.create({id: objectIdLikeString, name: 'John'}, function(err, user) { + user.id.should.be.an.instanceOf(ds.ObjectID); + user.id.should.eql(ObjectID(objectIdLikeString)); + User.findById(objectIdLikeString, function(err, user) { + user.should.not.be.null(); + done(err, user); + }); + }); + }); + + it('should find model with string id', function(done) { + User.create({id: 'a', name: 'John'}, function(err, user) { + user.id.should.be.an.instanceOf(String); + user.id.should.equal('a'); + User.findById('a', function(err, user) { + user.should.not.be.null(); + done(err, user); + }); + }); + }); + }); + + context('set to true', function() { + var User = ds.createModel( + 'user2', + { + id: {type: String, id: true}, + name: String, + }, + {strictObjectIDCoercion: true} + ); + + beforeEach(function(done) { + User.deleteAll(done); + }); + + it('should not find model with ObjectID id', function(done) { + User.create({name: 'John'}, function(err, user) { + user.id.should.not.be.an.instanceOf(ds.ObjectID); + User.findById(user.id, function(err, user) { + (user === null).should.be.true(); + done(err, user); + }); + }); + }); + + it('should find model with ObjectID-like string id', function(done) { + User.create({id: objectIdLikeString, name: 'John'}, function(err, user) { + user.id.should.not.be.an.instanceOf(ds.ObjectID); + user.id.should.eql(objectIdLikeString); + User.findById(objectIdLikeString, function(err, user) { + user.should.not.be.empty(); + done(err, user); + }); + }); + }); + + it('should find model with string id', function(done) { + User.create({id: 'a', name: 'John'}, function(err, user) { + user.id.should.be.an.instanceOf(String); + user.id.should.equal('a'); + User.findById('a', function(err, user) { + user.should.not.be.empty(); + done(err, user); + }); + }); + }); + }); + + context('set to true, id type set to `ObjectID`', function() { + var User = ds.createModel( + 'user3', + { + id: {type: String, id: true, mongodb: {dataType: 'ObjectID'}}, + name: String, + }, + {strictObjectIDCoercion: true} + ); + + beforeEach(function(done) { + User.deleteAll(done); + }); + + it('should find model with ObjectID id', function(done) { + User.create({name: 'John'}, function(err, user) { + user.id.should.be.an.instanceOf(ds.ObjectID); + User.findById(user.id, function(err, user) { + user.should.not.be.null(); + done(err, user); + }); + }); + }); + + // This works by coercing string to ObjectID, overriding `strictObjectIDCoercion: true` + it('should find model with ObjectID-like id', function(done) { + User.create({id: objectIdLikeString, name: 'John'}, function(err, user) { + user.id.should.be.an.instanceOf(ds.ObjectID); + user.id.should.eql(ObjectID(objectIdLikeString)); + User.findById(objectIdLikeString, function(err, user) { + user.should.not.be.null(); + done(err, user); + }); + }); + }); + + it('should find model with string id', function(done) { + User.create({id: 'a', name: 'John'}, function(err, user) { + user.id.should.be.an.instanceOf(String); + user.id.should.equal('a'); + User.findById('a', function(err, user) { + user.should.not.be.null(); + done(err, user); + }); + }); + }); + + it('should update model with ObjectID id', function(done) { + User.create({name: 'John'}, function(err, user) { + User.update({id: user.id, name: 'Jon'}, function(err) { + User.findById(user.id, function(err, user) { + user.name.should.equal('Jon'); + done(err, user); + }); + }); + }); + }); + + it('should update model with ObjectID-like id', function(done) { + User.create({id: objectIdLikeString, name: 'John'}, function(err, user) { + User.update({id: objectIdLikeString, name: 'Jon'}, function(err) { + User.findById(objectIdLikeString, function(err, user) { + user.name.should.equal('Jon'); + done(err, user); + }); + }); + }); + }); + + it('should update model with string id', function(done) { + User.create({id: 'a', name: 'John'}, function(err, user) { + User.update({id: 'a', name: 'Jon'}, function(err) { + User.findById('a', function(err, user) { + user.name.should.equal('Jon'); + done(err, user); + }); + }); + }); + }); + }); +});