New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

baucis

Package Overview
Dependencies
Maintainers
1
Versions
202
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

baucis - npm Package Compare versions

Comparing version

to
0.10.1

8

CHANGES.md
Baucis Change Log
=================
v0.10.1
-------
Improvements to optimistic locking. Adds the 'locking' controller option. When set to true, this option enables automatic version increments and strict version checking. When enabled, `__v` must always be sent with updates, and the baucis query must always have the `__v` key selected.
If this option is not enabled, no extra lock checking or version incrementing is performed outside what is normally done by Mongoose.
The 'always check version' controller option has been deprecated.
v0.10.0

@@ -5,0 +13,0 @@ -------

74

middleware/exec.js

@@ -58,8 +58,11 @@ // __Dependencies__

var operator = request.headers['x-baucis-update-operator'];
var conditions;
var updateWrapper = {};
var update = extend(request.body);
var versionKey = request.baucis.controller.get('schema').get('versionKey');
var alwaysCheckVersion = request.baucis.controller.get('always check version');
var version = update[versionKey];
var lock = request.baucis.controller.get('locking') === true;
var updateVersion = update[versionKey];
var done = function (error, saved) {
if (error) return next(error);
if (!saved) return response.send(404);
request.baucis.documents = saved;

@@ -69,48 +72,41 @@ next();

if (operator && validOperators.indexOf(operator) === -1) return next(new Error('Unsupported update operator: ' + operator));
if (alwaysCheckVersion && (version !== 0) && !version) return response.send(409);
if (lock && !Number.isFinite(updateVersion)) return response.send(409);
request.baucis.query.exec(function (error, doc) {
if (error) return next(error);
if (!doc) return response.send(404);
var previousVersion = doc[versionKey];
if (alwaysCheckVersion && !doc.isSelected(versionKey)) {
next(new Error('version key "'+ versionKey + '" was not selected.'));
return;
// Save with non-default operator
if (operator) {
if (validOperators.indexOf(operator) === -1) return next(new Error('Unsupported update operator: ' + operator));
// Ensure that some paths have been enabled for the operator.
if (!request.baucis.controller.get('allow ' + operator)) return next(new Error('Update operator not enabled for this controller: ' + operator));
// Make sure paths have been whitelisted for this operator.
if (request.baucis.controller.checkBadUpdateOperatorPaths(operator, Object.keys(update))) {
return next(new Error("Can't use update operator with non-whitelisted paths."));
}
if (previousVersion && (version || version === 0) && version < previousVersion) {
response.send(409);
return;
}
if (!operator) {
doc.set(update);
doc.save(done);
return;
}
// Non-default operator
var conditions = request.baucis.controller.getFindByConditions(request);
var updateWrapper = {};
conditions = request.baucis.controller.getFindByConditions(request);
if (lock) conditions[versionKey] = updateVersion;
updateWrapper[operator] = update;
request.baucis.controller.get('model').findOneAndUpdate(conditions, updateWrapper, done);
return;
}
// Oh man I really want this to trigger validation…
// var pathParts = 'arbitrary.$.llama'.split('.');
//
// doc.get(parts[0]) //arr
// subdoc = ...;// find one(s) that matches where for query
// subdoc.push(parts[2], val)
// Default update operator with `doc.save`.
request.baucis.query.exec(function (error, doc) {
if (error) return next(error);
if (!doc) return response.send(404);
// Ensure that some paths have been enabled for the operator.
if (!request.baucis.controller.get('allow ' + operator)) return next(new Error('Update operator not enabled for this controller: ' + operator));
var currentVersion = doc[versionKey];
// Make sure paths have been whitelisted for this operator.
if (request.baucis.controller.checkBadUpdateOperatorPaths(operator, Object.keys(update))) {
return next(new Error("Can't use update operator with non-whitelisted paths."));
if (lock) {
// Make sure the version key was selected.
if (!doc.isSelected(versionKey)) return next(new Error('Version key "'+ versionKey + '" was not selected.'));
// Update and current version have been found.
// Check if they're equal.
if (updateVersion !== currentVersion) response.send(409);
// One is not allowed to set __v and increment in the same update.
delete update[versionKey];
doc.increment();
}
request.baucis.controller.get('model').findOneAndUpdate(conditions, updateWrapper, done);
doc.set(update);
doc.save(done);
});

@@ -117,0 +113,0 @@ },

@@ -5,3 +5,3 @@ {

"homepage": "https://github.com/wprl/baucis",
"version": "0.10.0",
"version": "0.10.1",
"main": "index.js",

@@ -8,0 +8,0 @@ "scripts": {

@@ -1,2 +0,2 @@

baucis v0.10.0
baucis v0.10.1
==============

@@ -230,3 +230,3 @@

| head, get, post, put, del | May be set to false to disable those HTTP verbs completely for the controller |
| always check version | Force all PUTs to send the document version (__v). By default, if a version is not sent with an update no version checking is performed. |
| locking | Enable optimistic locking. Requires that all PUTs must send the document version (__v) and will send a 409 response if there is a version conflict. |

@@ -233,0 +233,0 @@ An example of embedding a controller within another controller

@@ -248,3 +248,3 @@ var expect = require('expect.js');

url: 'http://localhost:8012/api/v1/stores/123/tools/' + id,
json: { name: 'Screwdriver', __v: body[0].__v + 10 }
json: { name: 'Screwdriver' }
};

@@ -271,3 +271,2 @@ request.put(options, function (error, response, body) {

expect(body[0]).to.have.property('name', 'Axe');
expect()

@@ -472,3 +471,3 @@ var id = body[0]._id;

expect(response).to.have.property('statusCode', 500);
expect(body).to.contain('Error: The &quot;X-Baucis-Push header&quot; is deprecated. Use &quot;X-Baucis-Update-Operator: $push&quot; instead.');
expect(body).to.contain('Error: The "X-Baucis-Push header" is deprecated. Use "X-Baucis-Update-Operator: $push" instead.');
done();

@@ -744,18 +743,24 @@ });

var options = {
url: 'http://localhost:8012/api/v1/stores/Westlake',
url: 'http://localhost:8012/api/v1/liens',
json: true,
body: { __v: 10 }
body: { title: 'Franklin' }
};
request.put(options, function (error, response, body) {
request.post(options, function (error, response, body) {
if (error) return done(error);
expect(response).to.have.property('statusCode', 200);
expect(response).to.have.property('statusCode', 201);
var options = {
url: 'http://localhost:8012/api/v1/stores/Westlake',
url: 'http://localhost:8012/api/v1/liens/' + body._id,
json: true,
body: { __v: 0 }
body: { title: 'Ranken', __v: 0 }
};
request.put(options, function (error, response, body) {
if (error) return done(error);
expect(response).to.have.property('statusCode', 409);
done();
request.put(options, function (error, response, body) {
if (error) return done(error);
expect(response).to.have.property('statusCode', 409);
done();
});
});

@@ -765,6 +770,7 @@ });

it('should not send "409 Conflict" if there is no version conflict (equal)', function (done) {
it('should send "409 Conflict" if there is a version conflict (greater than)', function (done) {
var options = {
url: 'http://localhost:8012/api/v1/cheeses/Camembert',
json: true
url: 'http://localhost:8012/api/v1/liens',
json: true,
body: { title: 'Smithton' }
};

@@ -776,9 +782,9 @@ request.get(options, function (error, response, body) {

var options = {
url: 'http://localhost:8012/api/v1/cheeses/Camembert',
url: 'http://localhost:8012/api/v1/liens/' + body[1]._id,
json: true,
body: { __v: body.__v }
body: { __v: body[1].__v + 10 }
};
request.put(options, function (error, response, body) {
if (error) return done(error);
expect(response).to.have.property('statusCode', 200);
expect(response).to.have.property('statusCode', 409);
done();

@@ -789,5 +795,5 @@ });

it('should not send "409 Conflict" if there is no version conflict (greater than)', function (done) {
it('should not send "409 Conflict" if there is no version conflict (equal)', function (done) {
var options = {
url: 'http://localhost:8012/api/v1/cheeses/Camembert',
url: 'http://localhost:8012/api/v1/liens',
json: true

@@ -800,5 +806,5 @@ };

var options = {
url: 'http://localhost:8012/api/v1/cheeses/Camembert',
url: 'http://localhost:8012/api/v1/liens/' + body[1]._id,
json: true,
body: { __v: body.__v + 10 }
body: { __v: body[1].__v }
};

@@ -813,29 +819,53 @@ request.put(options, function (error, response, body) {

it('should send "409 Conflict" if alwaysCheckVersion is enabled and no version is sent', function (done) {
it('should cause an error if locking is enabled and no version is selected', function (done) {
var options = {
url: 'http://localhost:8012/api/v1/stores/Westlake',
url: 'http://localhost:8012/api/v1/liens',
json: true,
body: { }
body: { title: 'Forest Expansion' }
};
request.put(options, function (error, response, body) {
request.get(options, function (error, response, body) {
if (error) return done(error);
expect(response).to.have.property('statusCode', 409);
done();
expect(response).to.have.property('statusCode', 200);
var options = {
url: 'http://localhost:8012/api/v1/liens/' + body[0]._id,
json: true,
qs: { select: '-__v' },
body: { __v: 1000 }
};
request.put(options, function (error, response, body) {
if (error) return done(error);
expect(response).to.have.property('statusCode', 500);
done();
});
});
});
it('should cause an error if alwaysCheckVersion is enabled and no version is selected', function (done) {
it('should cause an error if locking is enabled and no version is selected', function (done) {
var options = {
url: 'http://localhost:8012/api/v1/stores/Westlake',
url: 'http://localhost:8012/api/v1/liens',
json: true,
qs: { select: '-__v' },
body: { __v: 1000 }
body: { title: 'Forest Expansion' }
};
request.put(options, function (error, response, body) {
request.get(options, function (error, response, body) {
if (error) return done(error);
expect(response).to.have.property('statusCode', 500);
done();
expect(response).to.have.property('statusCode', 200);
var options = {
url: 'http://localhost:8012/api/v1/liens/' + body[0]._id,
json: true,
qs: { select: '-__v' },
body: { __v: 1000 }
};
request.put(options, function (error, response, body) {
if (error) return done(error);
expect(response).to.have.property('statusCode', 500);
done();
});
});
});
it('should not send 409 if locking is not enabled');
});

@@ -22,7 +22,2 @@ var mongoose = require('mongoose');

Stores.on('save', function (next) {
this.increment();
next();
});
var Tools = new Schema({

@@ -44,9 +39,6 @@ name: { type: String, required: true },

Cheese.on('save', function (next) {
this.increment();
next();
});
var Beans = new Schema({ koji: Boolean });
var Deans = new Schema({ room: { type: Number, unique: true } });
var Liens = new Schema({ title: String });
var Means = new Schema({ average: Number });

@@ -58,2 +50,4 @@ if (!mongoose.models['tool']) mongoose.model('tool', Tools);

if (!mongoose.models['dean']) mongoose.model('dean', Deans);
if (!mongoose.models['lien']) mongoose.model('lien', Liens);
if (!mongoose.models['mean']) mongoose.model('mean', Means);

@@ -83,4 +77,3 @@ // Tools embedded controller

findBy: 'name',
select: '-mercoledi',
'always check version': true
select: '-mercoledi'
});

@@ -133,5 +126,21 @@

baucis.rest({
singular: 'lien',
locking: true
});
baucis.rest({
singular: 'mean',
locking: true,
'always check version': true
});
app = express();
app.use('/api/v1', baucis());
app.use(function (error, request, response, next) {
if (error) return response.send(500, error.toString());
next();
});
server = app.listen(8012);

@@ -138,0 +147,0 @@

@@ -59,2 +59,7 @@ var mongoose = require('mongoose');

app.use(function (error, request, response, next) {
if (error) return response.send(500, error.toString());
next();
});
server = app.listen(8012);

@@ -61,0 +66,0 @@

@@ -104,2 +104,7 @@ // __Dependencies__

app.use(function (error, request, response, next) {
if (error) return response.send(500, error.toString());
next();
});
server = app.listen(8012);

@@ -106,0 +111,0 @@