mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-13 14:39:52 +03:00
Merge pull request #6956 from ErisDS/version-mismatch
Version matching middleware
This commit is contained in:
commit
6826a6516b
@ -18,6 +18,7 @@ var _ = require('lodash'),
|
||||
DataImportError = require('./data-import-error'),
|
||||
TooManyRequestsError = require('./too-many-requests-error'),
|
||||
TokenRevocationError = require('./token-revocation-error'),
|
||||
VersionMismatchError = require('./version-mismatch-error'),
|
||||
i18n = require('../i18n'),
|
||||
config,
|
||||
errors,
|
||||
@ -445,3 +446,4 @@ module.exports.DataImportError = DataImportError;
|
||||
module.exports.MethodNotAllowedError = MethodNotAllowedError;
|
||||
module.exports.TooManyRequestsError = TooManyRequestsError;
|
||||
module.exports.TokenRevocationError = TokenRevocationError;
|
||||
module.exports.VersionMismatchError = VersionMismatchError;
|
||||
|
14
core/server/errors/version-mismatch-error.js
Normal file
14
core/server/errors/version-mismatch-error.js
Normal file
@ -0,0 +1,14 @@
|
||||
// # Version mismatch error
|
||||
// Custom error class with status code and type prefilled.
|
||||
|
||||
function VersionMismatchError(message) {
|
||||
this.message = message;
|
||||
this.stack = new Error().stack;
|
||||
this.statusCode = 400;
|
||||
this.errorType = this.name;
|
||||
}
|
||||
|
||||
VersionMismatchError.prototype = Object.create(Error.prototype);
|
||||
VersionMismatchError.prototype.name = 'VersionMismatchError';
|
||||
|
||||
module.exports = VersionMismatchError;
|
20
core/server/middleware/api/version-match.js
Normal file
20
core/server/middleware/api/version-match.js
Normal file
@ -0,0 +1,20 @@
|
||||
var errors = require('../../errors'),
|
||||
i18n = require('../../i18n');
|
||||
|
||||
function checkVersionMatch(req, res, next) {
|
||||
var requestVersion = req.get('X-Ghost-Version'),
|
||||
currentVersion = res.locals.safeVersion;
|
||||
|
||||
if (requestVersion && requestVersion !== currentVersion) {
|
||||
return next(new errors.VersionMismatchError(
|
||||
i18n.t(
|
||||
'errors.middleware.api.versionMismatch',
|
||||
{requestVersion: requestVersion, currentVersion: currentVersion}
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
module.exports = checkVersionMatch;
|
@ -27,6 +27,7 @@ var bodyParser = require('body-parser'),
|
||||
staticTheme = require('./static-theme'),
|
||||
themeHandler = require('./theme-handler'),
|
||||
uncapitalise = require('./uncapitalise'),
|
||||
versionMatch = require('./api/version-match'),
|
||||
cors = require('./cors'),
|
||||
netjet = require('netjet'),
|
||||
labs = require('./labs'),
|
||||
@ -50,7 +51,8 @@ middleware = {
|
||||
requiresAuthorizedUserPublicAPI: auth.requiresAuthorizedUserPublicAPI,
|
||||
errorHandler: errors.handleAPIError,
|
||||
cors: cors,
|
||||
labs: labs
|
||||
labs: labs,
|
||||
versionMatch: versionMatch
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,10 @@ apiRoutes = function apiRoutes(middleware) {
|
||||
// alias delete with del
|
||||
router.del = router.delete;
|
||||
|
||||
// Check version matches for API requests, depends on res.locals.safeVersion being set
|
||||
// Therefore must come after themeHandler.ghostLocals, for now
|
||||
router.use(middleware.api.versionMatch);
|
||||
|
||||
// ## CORS pre-flight check
|
||||
router.options('*', middleware.api.cors);
|
||||
|
||||
|
@ -62,6 +62,9 @@
|
||||
}
|
||||
},
|
||||
"middleware": {
|
||||
"api": {
|
||||
"versionMismatch": "Request for version {requestVersion} does not match current version {currentVersion}."
|
||||
},
|
||||
"auth": {
|
||||
"clientAuthenticationFailed": "Client Authentication Failed",
|
||||
"clientCredentialsNotProvided": "Client credentials were not provided",
|
||||
|
@ -235,4 +235,27 @@ describe('Public API', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('throws version mismatch error when request includes a version', function (done) {
|
||||
request.get(testUtils.API.getApiQuery('posts/?client_id=ghost-admin&client_secret=not_available'))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.set('X-Ghost-Version', '0.3')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(400)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
var jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
|
||||
jsonResponse.errors[0].errorType.should.eql('VersionMismatchError');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
56
core/test/unit/middleware/api/version-match_spec.js
Normal file
56
core/test/unit/middleware/api/version-match_spec.js
Normal file
@ -0,0 +1,56 @@
|
||||
/*globals describe, beforeEach, afterEach, it*/
|
||||
var should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
|
||||
versionMatch = require('../../../../server/middleware/api/version-match'),
|
||||
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
// To stop jshint complaining
|
||||
should.equal(true, true);
|
||||
|
||||
describe('Version Mismatch', function () {
|
||||
var req, res, getStub, nextStub;
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
getStub = sandbox.stub();
|
||||
nextStub = sandbox.stub();
|
||||
|
||||
req = {
|
||||
get: getStub
|
||||
};
|
||||
res = {
|
||||
locals: {
|
||||
safeVersion: '0.7'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
it('should call next if request does not include a version', function () {
|
||||
versionMatch(req, res, nextStub);
|
||||
|
||||
nextStub.calledOnce.should.be.true();
|
||||
nextStub.firstCall.args.should.be.empty();
|
||||
});
|
||||
|
||||
it('should call next if versions match', function () {
|
||||
getStub.returns('0.7');
|
||||
versionMatch(req, res, nextStub);
|
||||
|
||||
nextStub.calledOnce.should.be.true();
|
||||
nextStub.firstCall.args.should.be.empty();
|
||||
});
|
||||
|
||||
it('should throw VersionMismatchError if request includes incorrect version', function () {
|
||||
getStub.returns('0.6');
|
||||
versionMatch(req, res, nextStub);
|
||||
|
||||
nextStub.calledOnce.should.be.true();
|
||||
nextStub.firstCall.args.should.have.lengthOf(1);
|
||||
nextStub.firstCall.args[0].should.have.property('errorType', 'VersionMismatchError');
|
||||
nextStub.firstCall.args[0].should.have.property('statusCode', 400);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user