diff --git a/lib/index.js b/lib/index.js index 6fbfb932e5c..6edd382ae80 100644 --- a/lib/index.js +++ b/lib/index.js @@ -933,6 +933,51 @@ Mongoose.prototype.DocumentProvider = require('./document_provider'); Mongoose.prototype.ObjectId = SchemaTypes.ObjectId; +/** + * Returns true if Mongoose can cast the given value to an ObjectId, or + * false otherwise. + * + * ####Example: + * + * mongoose.isValidObjectId(new mongoose.Types.ObjectId()); // true + * mongoose.isValidObjectId('0123456789ab'); // true + * mongoose.isValidObjectId(6); // false + * + * @method isValidObjectId + * @api public + */ + +Mongoose.prototype.isValidObjectId = function(v) { + if (v == null) { + return true; + } + const base = this || mongoose; + const ObjectId = base.driver.get().ObjectId; + if (v instanceof ObjectId) { + return true; + } + + if (v._id != null) { + if (v._id instanceof ObjectId) { + return true; + } + if (v._id.toString instanceof Function) { + v = v._id.toString(); + return typeof v === 'string' && (v.length === 12 || v.length === 24); + } + } + + if (v.toString instanceof Function) { + v = v.toString(); + } + + if (typeof v === 'string' && (v.length === 12 || v.length === 24)) { + return true; + } + + return false; +}; + /** * The Mongoose Decimal128 [SchemaType](/docs/schematypes.html). Used for * declaring paths in your schema that should be diff --git a/test/index.test.js b/test/index.test.js index 5e3c643cd4f..e24407979a8 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -712,6 +712,12 @@ describe('mongoose module:', function() { }); }); + it('isValidObjectId (gh-3823)', function() { + assert.ok(mongoose.isValidObjectId('0123456789ab')); + assert.ok(mongoose.isValidObjectId(new mongoose.Types.ObjectId())); + assert.ok(!mongoose.isValidObjectId(6)); + }); + describe('exports', function() { function test(mongoose) { assert.equal(typeof mongoose.version, 'string');