mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-23 19:02:29 +03:00
Handled invalid timestamp format in filters
fix https://linear.app/tryghost/issue/SLO-85/fix-http-500-on-contentposts - in the event we give the incorrect format in a filter, MySQL will throw an error and we'll throw a HTTP 500 error - we can capture this error and return a more useful error to the user - ideally we'd do this in a validation step before attempting the query, but parsing this out of NQL and detecting which columns are DATETIME could be quite tricky
This commit is contained in:
parent
82c612bad9
commit
ae88dc8548
@ -4909,3 +4909,21 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Posts Content API Errors upon invalid filter value 1: [body] 1`] = `
|
||||
Object {
|
||||
"errors": Array [
|
||||
Object {
|
||||
"code": "ER_WRONG_VALUE",
|
||||
"context": "Invalid value select count(distinct posts.id) as aggregate from \`posts\` where (\`posts\`.\`status\` = 'published' and (\`posts\`.\`published_at\` < '1715091791890' and \`posts\`.\`type\` = 'post')) - Incorrect DATETIME value: '1715091791890'",
|
||||
"details": null,
|
||||
"ghostErrorCode": null,
|
||||
"help": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"message": "Validation error, cannot list posts.",
|
||||
"property": null,
|
||||
"type": "ValidationError",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
@ -5,7 +5,7 @@ const testUtils = require('../../utils');
|
||||
const models = require('../../../core/server/models');
|
||||
|
||||
const {agentProvider, fixtureManager, matchers, mockManager} = require('../../utils/e2e-framework');
|
||||
const {anyArray, anyContentVersion, anyEtag, anyUuid, anyISODateTimeWithTZ} = matchers;
|
||||
const {anyArray, anyContentVersion, anyErrorId, anyEtag, anyUuid, anyISODateTimeWithTZ} = matchers;
|
||||
|
||||
const postMatcher = {
|
||||
published_at: anyISODateTimeWithTZ,
|
||||
@ -93,6 +93,21 @@ describe('Posts Content API', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Errors upon invalid filter value', async function () {
|
||||
if (process.env.NODE_ENV !== 'testing-mysql') {
|
||||
this.skip();
|
||||
}
|
||||
|
||||
await agent
|
||||
.get(`posts/?filter=published_at%3A%3C%271715091791890%27`)
|
||||
.expectStatus(422)
|
||||
.matchBodySnapshot({
|
||||
errors: [{
|
||||
id: anyErrorId
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
it('Can filter posts by tag', async function () {
|
||||
const res = await agent.get('posts/?filter=tag:kitchen-sink,featured:true&include=tags')
|
||||
.expectStatus(200)
|
||||
|
@ -9,6 +9,7 @@ const tpl = require('@tryghost/tpl');
|
||||
|
||||
const messages = {
|
||||
genericError: 'An unexpected error occurred, please try again.',
|
||||
invalidValue: 'Invalid value',
|
||||
pageNotFound: 'Page not found',
|
||||
resourceNotFound: 'Resource not found',
|
||||
methodNotAcceptableVersionAhead: {
|
||||
@ -92,12 +93,21 @@ module.exports.prepareError = function prepareError(err, req, res, next) {
|
||||
} else if (isDependencyInStack('mysql2', err)) {
|
||||
// we don't want to return raw database errors to our users
|
||||
err.sqlErrorCode = err.code;
|
||||
err = new errors.InternalServerError({
|
||||
err: err,
|
||||
message: tpl(messages.genericError),
|
||||
statusCode: err.statusCode,
|
||||
code: 'UNEXPECTED_ERROR'
|
||||
});
|
||||
|
||||
if (err.code === 'ER_WRONG_VALUE') {
|
||||
err = new errors.ValidationError({
|
||||
message: tpl(messages.invalidValue),
|
||||
context: err.message,
|
||||
err
|
||||
});
|
||||
} else {
|
||||
err = new errors.InternalServerError({
|
||||
err: err,
|
||||
message: tpl(messages.genericError),
|
||||
statusCode: err.statusCode,
|
||||
code: 'UNEXPECTED_ERROR'
|
||||
});
|
||||
}
|
||||
// For everything else, create a generic 500 error, with context set to the original error message
|
||||
} else {
|
||||
err = new errors.InternalServerError({
|
||||
|
@ -103,7 +103,7 @@ describe('Prepare Error', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Correctly prepares a mysql2 error', function (done) {
|
||||
it('Correctly prepares a known ER_WRONG_VALUE mysql2 error', function (done) {
|
||||
let error = new Error('select anything from anywhere where something = anything;');
|
||||
|
||||
error.stack += '\n';
|
||||
@ -112,6 +112,29 @@ describe('Prepare Error', function () {
|
||||
error.sql = 'select anything from anywhere where something = anything;';
|
||||
error.sqlMessage = 'Incorrect DATETIME value: 3234234234';
|
||||
|
||||
prepareError(error, {}, {
|
||||
set: () => {}
|
||||
}, (err) => {
|
||||
assert.equal(err.statusCode, 422);
|
||||
assert.equal(err.name, 'ValidationError');
|
||||
assert.equal(err.message, 'Invalid value');
|
||||
assert.equal(err.code, 'ER_WRONG_VALUE');
|
||||
assert.equal(err.sqlErrorCode, 'ER_WRONG_VALUE');
|
||||
assert.equal(err.sql, 'select anything from anywhere where something = anything;');
|
||||
assert.equal(err.sqlMessage, 'Incorrect DATETIME value: 3234234234');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Correctly prepares an unknown mysql2 error', function (done) {
|
||||
let error = new Error('select anything from anywhere where something = anything;');
|
||||
|
||||
error.stack += '\n';
|
||||
error.stack += path.join('node_modules', 'mysql2', 'lib');
|
||||
error.code = 'ER_BAD_FIELD_ERROR';
|
||||
error.sql = 'select anything from anywhere where something = anything;';
|
||||
error.sqlMessage = 'Incorrect value: erororoor';
|
||||
|
||||
prepareError(error, {}, {
|
||||
set: () => {}
|
||||
}, (err) => {
|
||||
@ -119,9 +142,9 @@ describe('Prepare Error', function () {
|
||||
assert.equal(err.name, 'InternalServerError');
|
||||
assert.equal(err.message, 'An unexpected error occurred, please try again.');
|
||||
assert.equal(err.code, 'UNEXPECTED_ERROR');
|
||||
assert.equal(err.sqlErrorCode, 'ER_WRONG_VALUE');
|
||||
assert.equal(err.sqlErrorCode, 'ER_BAD_FIELD_ERROR');
|
||||
assert.equal(err.sql, 'select anything from anywhere where something = anything;');
|
||||
assert.equal(err.sqlMessage, 'Incorrect DATETIME value: 3234234234');
|
||||
assert.equal(err.sqlMessage, 'Incorrect value: erororoor');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user