mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Added extra validation for some settings of array type
refs https://github.com/TryGhost/Team/issues/754
refs a7dec233ba
- Additional validation protects from problems like the ones in refed commit from even getting through to the database.
- At the moment only used notificatons and couple more settings to ensure they are arrays when passed into the API. This is to avoid making big change in settings straight away - this is a problematic area which needs cautious approach.
- Ideally in the future the list of settings to check the "array" type (and other types) should be automatically generated based on the default-settings.json (or whatever way we define settings in the db a that moment)
- There's an ugly code-tripplication going on in this change. This is a separate topic that will be addressed once we work on API cleanup.
This commit is contained in:
parent
4fe723cd1b
commit
d9ddc2db6a
6 changed files with 120 additions and 3 deletions
|
@ -1,7 +1,7 @@
|
|||
const Promise = require('bluebird');
|
||||
const _ = require('lodash');
|
||||
const i18n = require('../../../../../../shared/i18n');
|
||||
const {NotFoundError} = require('@tryghost/errors');
|
||||
const {NotFoundError, ValidationError} = require('@tryghost/errors');
|
||||
|
||||
module.exports = {
|
||||
read(apiConfig, frame) {
|
||||
|
@ -27,6 +27,30 @@ module.exports = {
|
|||
})
|
||||
}));
|
||||
}
|
||||
|
||||
// TODO: the below array is INCOMPLETE
|
||||
// it should include all setting values that have array as a type
|
||||
const arrayTypeSettings = [
|
||||
'notifications',
|
||||
'navigation',
|
||||
'secondary_navigation'
|
||||
];
|
||||
|
||||
if (arrayTypeSettings.includes(setting.key)) {
|
||||
const typeError = new ValidationError({
|
||||
message: `Value in ${setting.key} should be an array.`,
|
||||
property: 'value'
|
||||
});
|
||||
|
||||
try {
|
||||
const value = JSON.parse(setting.value);
|
||||
if (!_.isArray(value)) {
|
||||
errors.push(typeError);
|
||||
}
|
||||
} catch (err) {
|
||||
errors.push(typeError);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.length) {
|
||||
|
|
|
@ -33,6 +33,30 @@ module.exports = {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: the below array is INCOMPLETE
|
||||
// it should include all setting values that have array as a type
|
||||
const arrayTypeSettings = [
|
||||
'notifications',
|
||||
'navigation',
|
||||
'secondary_navigation'
|
||||
];
|
||||
|
||||
if (arrayTypeSettings.includes(setting.key)) {
|
||||
const typeError = new ValidationError({
|
||||
message: `Value in ${setting.key} should be an array.`,
|
||||
property: 'value'
|
||||
});
|
||||
|
||||
try {
|
||||
const value = JSON.parse(setting.value);
|
||||
if (!_.isArray(value)) {
|
||||
errors.push(typeError);
|
||||
}
|
||||
} catch (err) {
|
||||
errors.push(typeError);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.length) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const Promise = require('bluebird');
|
||||
const _ = require('lodash');
|
||||
const i18n = require('../../../../../../shared/i18n');
|
||||
const {NotFoundError} = require('@tryghost/errors');
|
||||
const {NotFoundError, ValidationError} = require('@tryghost/errors');
|
||||
|
||||
module.exports = {
|
||||
read(apiConfig, frame) {
|
||||
|
@ -27,6 +27,30 @@ module.exports = {
|
|||
})
|
||||
}));
|
||||
}
|
||||
|
||||
// TODO: the below array is INCOMPLETE
|
||||
// it should include all setting values that have array as a type
|
||||
const arrayTypeSettings = [
|
||||
'notifications',
|
||||
'navigation',
|
||||
'secondary_navigation'
|
||||
];
|
||||
|
||||
if (arrayTypeSettings.includes(setting.key)) {
|
||||
const typeError = new ValidationError({
|
||||
message: `Value in ${setting.key} should be an array.`,
|
||||
property: 'value'
|
||||
});
|
||||
|
||||
try {
|
||||
const value = JSON.parse(setting.value);
|
||||
if (!_.isArray(value)) {
|
||||
errors.push(typeError);
|
||||
}
|
||||
} catch (err) {
|
||||
errors.push(typeError);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.length) {
|
||||
|
|
|
@ -1227,10 +1227,25 @@ describe('Settings API (canary)', function () {
|
|||
dbSettings.should.have.property('twitter_image', '__GHOST_URL__/content/images/twitter_image.png');
|
||||
});
|
||||
|
||||
it('Can only send array values for keys defined with array type', async function () {
|
||||
const settingsToChange = {
|
||||
settings: [
|
||||
{key: 'navigation', value: 'not an array'}
|
||||
]
|
||||
};
|
||||
|
||||
await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingsToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(422);
|
||||
});
|
||||
|
||||
it('Cannot edit notifications key through API', async function () {
|
||||
const settingsToChange = {
|
||||
settings: [
|
||||
{key: 'notifications', value: `anything`}
|
||||
{key: 'notifications', value: JSON.stringify(['do not touch me'])}
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
@ -708,6 +708,21 @@ describe('Settings API (v2)', function () {
|
|||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
});
|
||||
|
||||
it('Can only send array values for keys defined with array type', async function () {
|
||||
const settingsToChange = {
|
||||
settings: [
|
||||
{key: 'navigation', value: 'not an array'}
|
||||
]
|
||||
};
|
||||
|
||||
await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingsToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(422);
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Admin', function () {
|
||||
|
|
|
@ -702,6 +702,21 @@ describe('Settings API (v3)', function () {
|
|||
putBody.settings[0].key.should.eql('slack_username');
|
||||
putBody.settings[0].value.should.eql('can edit me');
|
||||
});
|
||||
|
||||
it('Can only send array values for keys defined with array type', async function () {
|
||||
const settingsToChange = {
|
||||
settings: [
|
||||
{key: 'navigation', value: 'not an array'}
|
||||
]
|
||||
};
|
||||
|
||||
await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingsToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(422);
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Admin', function () {
|
||||
|
|
Loading…
Add table
Reference in a new issue