Cannot use field names beginning with the $ sign

pull/2/head
Louis Chatriot 12 years ago
parent 0854009b22
commit 6c111067d8
  1. 21
      lib/datastore.js
  2. 22
      lib/model.js
  3. 9
      test/db.test.js
  4. 10
      test/model.test.js

@ -105,7 +105,6 @@ Datastore.prototype.insert = function (newDoc, cb) {
*/ */
Datastore.match = function (obj, query) { Datastore.match = function (obj, query) {
var match = true var match = true
//, queryKeys = Object.keys(query)
, i, k; , i, k;
Object.keys(query).forEach(function (k) { Object.keys(query).forEach(function (k) {
@ -223,14 +222,18 @@ Datastore.prototype.update = function (query, newDoc, options, cb) {
}); });
} }
, function () { // Perform the update , function () { // Perform the update
self.data.forEach(function (d) { try {
if (Datastore.match(d, query) && (multi || numReplaced === 0)) { self.data.forEach(function (d) {
numReplaced += 1; if (Datastore.match(d, query) && (multi || numReplaced === 0)) {
newData.push(model.modify(d, newDoc)); numReplaced += 1;
} else { newData.push(model.modify(d, newDoc));
newData.push(d); } else {
} newData.push(d);
}); }
});
} catch (err) {
return callback(err);
}
self.persistWholeDatabase(newData, function (err) { self.persistWholeDatabase(newData, function (err) {
if (err) { return callback(err); } if (err) { return callback(err); }

@ -7,6 +7,22 @@
var dateToJSON = function () { return { $$date: this.getTime() }; } var dateToJSON = function () { return { $$date: this.getTime() }; }
, originalDateToJSON = Date.prototype.toJSON , originalDateToJSON = Date.prototype.toJSON
/**
* Check a key, throw an error if the key is non valid
* @param {String} k key
* @param {Model} v value, needed to treat the Date edge case
* Non-treatable edge case here: if part of the object if of the form { $$date: number }
* Its serialized-then-deserialized version it will transformed into a Date object
* But you really need to want it to trigger such behaviour, even when warned not to use '$' at the beginning of the field names...
*/
function checkKey (k, v) {
if (k[0] === '$' && !(k === '$$date' && typeof v === 'number')) {
throw 'Keys cannot begin with the $ character';
}
}
/** /**
* 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
@ -19,10 +35,7 @@ function serialize (obj) {
Date.prototype.toJSON = dateToJSON; Date.prototype.toJSON = dateToJSON;
res = JSON.stringify(obj, function (k, v) { res = JSON.stringify(obj, function (k, v) {
// Non-treatable edge case here: if part of the object if of the form { $$date: number } checkKey(k, v);
// Its serialized-then-deserialized version it will transformed into a Date object
// But you really need to want it to trigger such behaviour, even when warned not to use '$' at the beginning of the field names...
if (k[0] === '$' && !(k === '$$date' && typeof v === 'number')) { throw 'Keys cannot begin with the $ character'; }
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean' || v === null) { return v; } if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean' || v === null) { return v; }
//if (v && v.constructor && v.constructor.name === 'Date') { console.log("==============="); return { $$date: v.toString() }; } //if (v && v.constructor && v.constructor.name === 'Date') { console.log("==============="); return { $$date: v.toString() }; }
@ -75,6 +88,7 @@ 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;

@ -422,6 +422,15 @@ describe('Database', function () {
}); });
}); });
it('Cannot perform update if the new document contains a field beginning by $', function (done) {
d.insert({ something: 'yup' }, function () {
d.update({}, { boom: { $badfield: 5 } }, { multi: false }, function (err) {
assert.isDefined(err);
done();
});
});
});
}); // ==== End of 'Update' ==== // }); // ==== End of 'Update' ==== //

@ -157,7 +157,15 @@ 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