Function dedicated to checking an object has the right format

pull/2/head
Louis Chatriot 12 years ago
parent 22fd30981e
commit 4045dd9e4a
  1. 27
      lib/model.js
  2. 34
      test/model.test.js

@ -6,6 +6,8 @@
var dateToJSON = function () { return { $$date: this.getTime() }; } var dateToJSON = function () { return { $$date: this.getTime() }; }
, originalDateToJSON = Date.prototype.toJSON , originalDateToJSON = Date.prototype.toJSON
, util = require('util')
;
/** /**
@ -23,6 +25,26 @@ function checkKey (k, v) {
} }
/**
* Check a DB object and throw an error if it's not valid
* Works by applying the above checkKey function to all fields recursively
*/
function checkObject (obj) {
if (util.isArray(obj)) {
obj.forEach(function (o) {
checkObject(o);
});
}
if (typeof obj === 'object') {
Object.keys(obj).forEach(function (k) {
checkKey(k, obj[k]);
checkObject(obj[k]);
});
}
}
/** /**
* Serialize an object to be persisted to a one-line string * Serialize an object to be persisted to a one-line string
* Accepted primitive types: Number, String, Boolean, Date, null * Accepted primitive types: Number, String, Boolean, Date, null
@ -88,7 +110,6 @@ function deepCopy (obj) {
if (typeof obj === 'object') { if (typeof obj === 'object') {
res = {}; res = {};
Object.keys(obj).forEach(function (k) { Object.keys(obj).forEach(function (k) {
checkKey(k, obj[k]);
res[k] = deepCopy(obj[k]); res[k] = deepCopy(obj[k]);
}); });
return res; return res;
@ -105,6 +126,9 @@ function deepCopy (obj) {
function modify (obj, updateQuery) { function modify (obj, updateQuery) {
updateQuery = deepCopy(updateQuery); updateQuery = deepCopy(updateQuery);
updateQuery._id = obj._id; updateQuery._id = obj._id;
checkObject(updateQuery);
return updateQuery; return updateQuery;
}; };
@ -113,4 +137,5 @@ function modify (obj, updateQuery) {
module.exports.serialize = serialize; module.exports.serialize = serialize;
module.exports.deserialize = deserialize; module.exports.deserialize = deserialize;
module.exports.deepCopy = deepCopy; module.exports.deepCopy = deepCopy;
module.exports.checkObject = checkObject;
module.exports.modify = modify; module.exports.modify = modify;

@ -127,6 +127,30 @@ describe('Model', function () {
}); // ==== End of 'Serialization, deserialization' ==== // }); // ==== End of 'Serialization, deserialization' ==== //
describe('Object checking', function () {
it('Field names beginning with a $ sign are forbidden', function () {
assert.isDefined(model.checkObject);
(function () {
model.checkObject({ $bad: true });
}).should.throw();
(function () {
model.checkObject({ some: 42, nested: { again: "no", $worse: true } });
}).should.throw();
// This shouldn't throw since "$actuallyok" is not a field name
model.checkObject({ some: 42, nested: [ 5, "no", "$actuallyok", true ] });
(function () {
model.checkObject({ some: 42, nested: [ 5, "no", "$actuallyok", true, { $hidden: "useless" } ] });
}).should.throw();
});
}); // ==== End of 'Object checking' ==== //
describe('Deep copying', function () { describe('Deep copying', function () {
it('Should be able to deep copy any serializable model', function () { it('Should be able to deep copy any serializable model', function () {
@ -157,16 +181,6 @@ describe('Model', function () {
res.subobj.b.should.equal('c'); res.subobj.b.should.equal('c');
}); });
it('Will throw an error if obj contains a field beginning by the $ sign', function () {
(function () {
model.deepCopy({ $something: true });
}).should.throw();
(function () {
model.deepCopy({ something: true, another: { $badfield: 'rrr' } });
}).should.throw();
});
}); // ==== End of 'Deep copying' ==== // }); // ==== End of 'Deep copying' ==== //
}); });

Loading…
Cancel
Save