Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions lib/cast/uuid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use strict';

const MongooseBuffer = require('../types/buffer');

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;
const Binary = MongooseBuffer.Binary;

module.exports = function castUUID(value) {
if (value == null) {
return value;
}

function newBuffer(initbuff) {
const buff = new MongooseBuffer(initbuff);
buff._subtype = 4;
return buff;
}

if (typeof value === 'string') {
if (UUID_FORMAT.test(value)) {
return stringToBinary(value);
} else {
throw new Error(`"${value}" is not a valid UUID string`);
}
}

if (Buffer.isBuffer(value)) {
return newBuffer(value);
}

if (value instanceof Binary) {
return newBuffer(value.value(true));
}

// Re: gh-647 and gh-3030, we're ok with casting using `toString()`
// **unless** its the default Object.toString, because "[object Object]"
// doesn't really qualify as useful data
if (value.toString && value.toString !== Object.prototype.toString) {
if (UUID_FORMAT.test(value.toString())) {
return stringToBinary(value.toString());
}
}

throw new Error(`"${value}" cannot be casted to a UUID`);
};

module.exports.UUID_FORMAT = UUID_FORMAT;

/**
* Helper function to convert the input hex-string to a buffer
* @param {String} hex The hex string to convert
* @returns {Buffer} The hex as buffer
* @api private
*/

function hex2buffer(hex) {
// use buffer built-in function to convert from hex-string to buffer
const buff = hex != null && Buffer.from(hex, 'hex');
return buff;
}

/**
* Convert a String to Binary
* @param {String} uuidStr The value to process
* @returns {MongooseBuffer} The binary to store
* @api private
*/

function stringToBinary(uuidStr) {
// Protect against undefined & throwing err
if (typeof uuidStr !== 'string') uuidStr = '';
const hex = uuidStr.replace(/[{}-]/g, ''); // remove extra characters
const bytes = hex2buffer(hex);
const buff = new MongooseBuffer(bytes);
buff._subtype = 4;

return buff;
}
73 changes: 3 additions & 70 deletions lib/schema/uuid.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,13 @@
const MongooseBuffer = require('../types/buffer');
const SchemaType = require('../schemaType');
const CastError = SchemaType.CastError;
const castUUID = require('../cast/uuid');
const utils = require('../utils');
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;
const UUID_FORMAT = castUUID.UUID_FORMAT;
const Binary = MongooseBuffer.Binary;

/**
* Helper function to convert the input hex-string to a buffer
* @param {String} hex The hex string to convert
* @returns {Buffer} The hex as buffer
* @api private
*/

function hex2buffer(hex) {
// use buffer built-in function to convert from hex-string to buffer
const buff = hex != null && Buffer.from(hex, 'hex');
return buff;
}

/**
* Convert a String to Binary
* @param {String} uuidStr The value to process
* @returns {MongooseBuffer} The binary to store
* @api private
*/

function stringToBinary(uuidStr) {
// Protect against undefined & throwing err
if (typeof uuidStr !== 'string') uuidStr = '';
const hex = uuidStr.replace(/[{}-]/g, ''); // remove extra characters
const bytes = hex2buffer(hex);
const buff = new MongooseBuffer(bytes);
buff._subtype = 4;

return buff;
}

/**
* Convert binary to a uuid string
* @param {Buffer|Binary|String} uuidBin The value to process
Expand Down Expand Up @@ -109,44 +79,7 @@ SchemaUUID.prototype.constructor = SchemaUUID;
* ignore
*/

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

function newBuffer(initbuff) {
const buff = new MongooseBuffer(initbuff);
buff._subtype = 4;
return buff;
}

if (typeof value === 'string') {
if (UUID_FORMAT.test(value)) {
return stringToBinary(value);
} else {
throw new CastError(SchemaUUID.schemaName, value, this.path);
}
}

if (Buffer.isBuffer(value)) {
return newBuffer(value);
}

if (value instanceof Binary) {
return newBuffer(value.value(true));
}

// Re: gh-647 and gh-3030, we're ok with casting using `toString()`
// **unless** its the default Object.toString, because "[object Object]"
// doesn't really qualify as useful data
if (value.toString && value.toString !== Object.prototype.toString) {
if (UUID_FORMAT.test(value.toString())) {
return stringToBinary(value.toString());
}
}

throw new CastError(SchemaUUID.schemaName, value, this.path);
};
SchemaUUID._cast = castUUID;

/**
* Attaches a getter for all UUID instances.
Expand Down
2 changes: 2 additions & 0 deletions test/schema.uuid.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ describe('SchemaUUID', function() {
const errors = res.errors;
assert.strictEqual(Object.keys(errors).length, 1);
assert.ok(errors.x instanceof mongoose.Error.CastError);

assert.ok(errors.x.reason.message.includes('not a valid UUID string'), errors.x.reason.message);
});

it('should work with $in and $nin and $all', async function() {
Expand Down
Loading