mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-04-08 02:52:39 -05:00
Refactored usage of the pre v4 "slack" setting
refs https://github.com/TryGhost/Ghost/issues/10318 - Change/compatibility table for this changeset: Importer + "slack_username" import - "slack_url" ignore + "slack.username" import - "slack.url" ignore v3 & canary/v4 Admin APIs GET /settings/ (browse) + "slack_username" present in response + "slack_url" present in response + "slack" present in response GET /settings/:settingName (read) + "slack_username" present in response + "slack_url" present in response + "slack" present in response PUT /settings/ (edit) + "slack_username" updates setting + "slack_url" updates setting + "slack" !NOTE! updates setting unless "slack_username" or "slack_ur"l are set (updated keys take priority) v2 Admin API GET /settings/ (browse) - "slack_username" NOT present in response - "slack_url" NOT present in response + "slack" present in response GET /settings/:settingName (read) - "slack_username" ignored (404) - "slack_url" ignored (404) - "slack" present in response PUT /settings/ (edit) - "slack_username" ignored (no error) - "slack_url" ignored (no error) + "slack" updates setting
This commit is contained in:
parent
12c28fe66e
commit
8880cc82c7
26 changed files with 6515 additions and 83 deletions
|
@ -53,7 +53,20 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
query(frame) {
|
||||
let setting = settingsCache.get(frame.options.key, {resolve: false});
|
||||
let setting;
|
||||
if (frame.options.key === 'slack') {
|
||||
const slackURL = settingsCache.get('slack_url', {resolve: false});
|
||||
const slackUsername = settingsCache.get('slack_username', {resolve: false});
|
||||
|
||||
setting = slackURL || slackUsername;
|
||||
setting.key = 'slack';
|
||||
setting.value = [{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}];
|
||||
} else {
|
||||
setting = settingsCache.get(frame.options.key, {resolve: false});
|
||||
}
|
||||
|
||||
if (!setting) {
|
||||
return Promise.reject(new NotFoundError({
|
||||
|
|
|
@ -3,6 +3,59 @@ const url = require('./utils/url');
|
|||
const typeGroupMapper = require('../../../../shared/serializers/input/utils/settings-filter-type-group-mapper');
|
||||
const settingsCache = require('../../../../../services/settings/cache');
|
||||
|
||||
const DEPRECATED_SETTINGS = [
|
||||
'bulk_email_settings',
|
||||
'slack'
|
||||
];
|
||||
|
||||
const deprecatedSupportedSettingsOneToManyMap = {
|
||||
slack: [{
|
||||
from: '[0].url',
|
||||
to: {
|
||||
key: 'slack_url',
|
||||
group: 'slack',
|
||||
type: 'string'
|
||||
}
|
||||
}, {
|
||||
from: '[0].username',
|
||||
to: {
|
||||
key: 'slack_username',
|
||||
group: 'slack',
|
||||
type: 'string'
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
const getMappedDeprecatedSettings = (settings) => {
|
||||
const mappedSettings = [];
|
||||
|
||||
for (const key in deprecatedSupportedSettingsOneToManyMap) {
|
||||
const deprecatedSetting = settings.find(setting => setting.key === key);
|
||||
|
||||
if (deprecatedSetting) {
|
||||
let deprecatedSettingValue;
|
||||
|
||||
try {
|
||||
deprecatedSettingValue = JSON.parse(deprecatedSetting.value);
|
||||
} catch (err) {
|
||||
// ignore the value if it's invalid
|
||||
}
|
||||
|
||||
if (deprecatedSettingValue) {
|
||||
deprecatedSupportedSettingsOneToManyMap[key].forEach(({from, to}) => {
|
||||
const value = _.get(deprecatedSettingValue, from);
|
||||
mappedSettings.push({
|
||||
key: to.key,
|
||||
value: value
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mappedSettings;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
browse(apiConfig, frame) {
|
||||
if (frame.options.type) {
|
||||
|
@ -48,8 +101,14 @@ module.exports = {
|
|||
return !settingFlagsArr.includes('RO');
|
||||
});
|
||||
|
||||
frame.data.settings = frame.data.settings.filter((setting) => {
|
||||
return setting.key !== 'bulk_email_settings';
|
||||
const mappedDeprecatedSettings = getMappedDeprecatedSettings(frame.data.settings);
|
||||
mappedDeprecatedSettings.forEach((setting) => {
|
||||
// NOTE: give priority for non-deprecated setting values if they exist
|
||||
const nonDeprecatedExists = frame.data.settings.find(s => s.key === setting.key);
|
||||
|
||||
if (!nonDeprecatedExists) {
|
||||
frame.data.settings.push(setting);
|
||||
}
|
||||
});
|
||||
|
||||
frame.data.settings.forEach((setting) => {
|
||||
|
@ -95,5 +154,10 @@ module.exports = {
|
|||
setting = url.forSetting(setting);
|
||||
}
|
||||
});
|
||||
|
||||
// Ignore all deprecated settings
|
||||
frame.data.settings = frame.data.settings.filter((setting) => {
|
||||
return DEPRECATED_SETTINGS.includes(setting.key) === false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -72,8 +72,12 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
if (frame.original.params.key === 'lang') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame.original.params.key === 'slack_url'
|
||||
|| frame.original.params.key === 'slack_username') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// CASE: edit
|
||||
if (frame.original.body && frame.original.body.settings) {
|
||||
frame.original.body.settings.forEach((setting) => {
|
||||
|
@ -89,6 +93,20 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
} else if (setting.key === 'default_locale') {
|
||||
const target = _.find(attrs, {key: 'lang'});
|
||||
target.key = 'default_locale';
|
||||
} else if (setting.key === 'slack') {
|
||||
const slackURL = _.cloneDeep(_.find(attrs, {key: 'slack_url'}));
|
||||
const slackUsername = _.cloneDeep(_.find(attrs, {key: 'slack_username'}));
|
||||
|
||||
if (slackURL || slackUsername) {
|
||||
const slack = slackURL || slackUsername;
|
||||
slack.key = 'slack';
|
||||
slack.value = JSON.stringify([{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}]);
|
||||
|
||||
attrs.push(slack);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -100,6 +118,8 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
const ghostFoot = _.cloneDeep(_.find(attrs, {key: 'codeinjection_foot'}));
|
||||
const timezone = _.cloneDeep(_.find(attrs, {key: 'timezone'}));
|
||||
const lang = _.cloneDeep(_.find(attrs, {key: 'lang'}));
|
||||
const slackURL = _.cloneDeep(_.find(attrs, {key: 'slack_url'}));
|
||||
const slackUsername = _.cloneDeep(_.find(attrs, {key: 'slack_username'}));
|
||||
|
||||
if (ghostHead) {
|
||||
ghostHead.key = 'ghost_head';
|
||||
|
@ -120,5 +140,16 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
lang.key = 'default_locale';
|
||||
attrs.push(lang);
|
||||
}
|
||||
|
||||
if (slackURL || slackUsername) {
|
||||
const slack = slackURL || slackUsername;
|
||||
slack.key = 'slack';
|
||||
slack.value = JSON.stringify([{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}]);
|
||||
|
||||
attrs.push(slack);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -102,9 +102,25 @@ const mapSettings = (attrs, frame) => {
|
|||
// `forSettings` step. This logic can be rewritten once we get rid of deprecated
|
||||
// fields completely.
|
||||
if (_.isArray(attrs)) {
|
||||
attrs = _.filter(attrs, (o) => {
|
||||
return o.key !== 'ghost_head' && o.key !== 'ghost_foot';
|
||||
});
|
||||
const keysToFilter = ['ghost_head', 'ghost_foot'];
|
||||
|
||||
// NOTE: to support edits of deprecated 'slack' setting artificial 'slack_url' and 'slack_username'
|
||||
// were added to the request body in the input serializer. These should not be returned in response
|
||||
// body unless directly requested
|
||||
if (frame.original.body && frame.original.body.settings) {
|
||||
const requestedEditSlackUrl = frame.original.body.settings.find(s => s.key === 'slack_url');
|
||||
const requestedEditSlackUsername = frame.original.body.settings.find(s => s.key === 'slack_username');
|
||||
|
||||
if (!requestedEditSlackUrl) {
|
||||
keysToFilter.push('slack_url');
|
||||
}
|
||||
|
||||
if (!requestedEditSlackUsername) {
|
||||
keysToFilter.push('slack_username');
|
||||
}
|
||||
}
|
||||
|
||||
attrs = _.filter(attrs, attr => !(keysToFilter.includes(attr.key)));
|
||||
}
|
||||
|
||||
return attrs;
|
||||
|
|
|
@ -51,7 +51,22 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
query(frame) {
|
||||
let setting = settingsCache.get(frame.options.key, {resolve: false});
|
||||
let setting;
|
||||
if (frame.options.key === 'slack') {
|
||||
const slackURL = settingsCache.get('slack_url', {resolve: false});
|
||||
const slackUsername = settingsCache.get('slack_username', {resolve: false});
|
||||
|
||||
setting = slackURL || slackUsername;
|
||||
setting.key = 'slack';
|
||||
setting.value = [{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}];
|
||||
} else if (frame.options.key === 'slack_url' || frame.options.key === 'slack_username') {
|
||||
// leave the value empty returning 404 for unknown in current API keys
|
||||
} else {
|
||||
setting = settingsCache.get(frame.options.key, {resolve: false});
|
||||
}
|
||||
|
||||
if (!setting) {
|
||||
return Promise.reject(new NotFoundError({
|
||||
|
|
|
@ -3,6 +3,59 @@ const url = require('./utils/url');
|
|||
const typeGroupMapper = require('../../../../shared/serializers/input/utils/settings-filter-type-group-mapper');
|
||||
const settingsCache = require('../../../../../services/settings/cache');
|
||||
|
||||
const DEPRECATED_SETTINGS = [
|
||||
'bulk_email_settings',
|
||||
'slack'
|
||||
];
|
||||
|
||||
const deprecatedSupportedSettingsOneToManyMap = {
|
||||
slack: [{
|
||||
from: '[0].url',
|
||||
to: {
|
||||
key: 'slack_url',
|
||||
group: 'slack',
|
||||
type: 'string'
|
||||
}
|
||||
}, {
|
||||
from: '[0].username',
|
||||
to: {
|
||||
key: 'slack_username',
|
||||
group: 'slack',
|
||||
type: 'string'
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
const getMappedDeprecatedSettings = (settings) => {
|
||||
const mappedSettings = [];
|
||||
|
||||
for (const key in deprecatedSupportedSettingsOneToManyMap) {
|
||||
const deprecatedSetting = settings.find(setting => setting.key === key);
|
||||
|
||||
if (deprecatedSetting) {
|
||||
let deprecatedSettingValue;
|
||||
|
||||
try {
|
||||
deprecatedSettingValue = JSON.parse(deprecatedSetting.value);
|
||||
} catch (err) {
|
||||
// ignore the value if it's invalid
|
||||
}
|
||||
|
||||
if (deprecatedSettingValue) {
|
||||
deprecatedSupportedSettingsOneToManyMap[key].forEach(({from, to}) => {
|
||||
const value = _.get(deprecatedSettingValue, from);
|
||||
mappedSettings.push({
|
||||
key: to.key,
|
||||
value: value
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mappedSettings;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
browse(apiConfig, frame) {
|
||||
if (frame.options.type) {
|
||||
|
@ -45,9 +98,7 @@ module.exports = {
|
|||
return !settingFlagsArr.includes('RO');
|
||||
});
|
||||
|
||||
frame.data.settings = frame.data.settings.filter((setting) => {
|
||||
return setting.key !== 'bulk_email_settings';
|
||||
});
|
||||
frame.data.settings.push(...getMappedDeprecatedSettings(frame.data.settings));
|
||||
|
||||
frame.data.settings.forEach((setting) => {
|
||||
const settingType = settings[setting.key] ? settings[setting.key].type : '';
|
||||
|
@ -87,5 +138,10 @@ module.exports = {
|
|||
setting = url.forSetting(setting);
|
||||
}
|
||||
});
|
||||
|
||||
// Ignore all deprecated settings
|
||||
frame.data.settings = frame.data.settings.filter((setting) => {
|
||||
return DEPRECATED_SETTINGS.includes(setting.key) === false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -75,6 +75,20 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
} else if (setting.key === 'default_locale') {
|
||||
const target = _.find(attrs, {key: 'timezone'});
|
||||
target.key = 'lang';
|
||||
} else if (setting.key === 'slack') {
|
||||
const slackURL = _.cloneDeep(_.find(attrs, {key: 'slack_url'}));
|
||||
const slackUsername = _.cloneDeep(_.find(attrs, {key: 'slack_username'}));
|
||||
|
||||
if (slackURL || slackUsername) {
|
||||
const slack = slackURL || slackUsername;
|
||||
slack.key = 'slack';
|
||||
slack.value = JSON.stringify([{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}]);
|
||||
|
||||
attrs.push(slack);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -86,6 +100,8 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
const ghostFoot = _.cloneDeep(_.find(attrs, {key: 'codeinjection_foot'}));
|
||||
const timezone = _.cloneDeep(_.find(attrs, {key: 'timezone'}));
|
||||
const lang = _.cloneDeep(_.find(attrs, {key: 'lang'}));
|
||||
const slackURL = _.cloneDeep(_.find(attrs, {key: 'slack_url'}));
|
||||
const slackUsername = _.cloneDeep(_.find(attrs, {key: 'slack_username'}));
|
||||
|
||||
if (ghostHead) {
|
||||
ghostHead.key = 'ghost_head';
|
||||
|
@ -106,6 +122,17 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
lang.key = 'default_locale';
|
||||
attrs.push(lang);
|
||||
}
|
||||
|
||||
if (slackURL || slackUsername) {
|
||||
const slack = slackURL || slackUsername;
|
||||
slack.key = 'slack';
|
||||
slack.value = JSON.stringify([{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}]);
|
||||
|
||||
attrs.push(slack);
|
||||
}
|
||||
} else {
|
||||
attrs.ghost_head = attrs.codeinjection_head;
|
||||
attrs.ghost_foot = attrs.codeinjection_foot;
|
||||
|
|
|
@ -87,8 +87,9 @@ const mapSettings = (attrs, frame) => {
|
|||
extraAttrs.forSettings(attrs, frame);
|
||||
|
||||
if (_.isArray(attrs)) {
|
||||
const DEPRECATED_KEYS = ['lang', 'timezone', 'accent_color', 'slack_url', 'slack_username'];
|
||||
attrs = _.filter(attrs, (o) => {
|
||||
return o.key !== 'lang' && o.key !== 'timezone' && o.key !== 'accent_color';
|
||||
return !DEPRECATED_KEYS.includes(o.key);
|
||||
});
|
||||
} else {
|
||||
delete attrs.lang;
|
||||
|
|
|
@ -53,7 +53,20 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
query(frame) {
|
||||
let setting = settingsCache.get(frame.options.key, {resolve: false});
|
||||
let setting;
|
||||
if (frame.options.key === 'slack') {
|
||||
const slackURL = settingsCache.get('slack_url', {resolve: false});
|
||||
const slackUsername = settingsCache.get('slack_username', {resolve: false});
|
||||
|
||||
setting = slackURL || slackUsername;
|
||||
setting.key = 'slack';
|
||||
setting.value = [{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}];
|
||||
} else {
|
||||
setting = settingsCache.get(frame.options.key, {resolve: false});
|
||||
}
|
||||
|
||||
if (!setting) {
|
||||
return Promise.reject(new NotFoundError({
|
||||
|
|
|
@ -3,6 +3,59 @@ const url = require('./utils/url');
|
|||
const typeGroupMapper = require('../../../../shared/serializers/input/utils/settings-filter-type-group-mapper');
|
||||
const settingsCache = require('../../../../../services/settings/cache');
|
||||
|
||||
const DEPRECATED_SETTINGS = [
|
||||
'bulk_email_settings',
|
||||
'slack'
|
||||
];
|
||||
|
||||
const deprecatedSupportedSettingsOneToManyMap = {
|
||||
slack: [{
|
||||
from: '[0].url',
|
||||
to: {
|
||||
key: 'slack_url',
|
||||
group: 'slack',
|
||||
type: 'string'
|
||||
}
|
||||
}, {
|
||||
from: '[0].username',
|
||||
to: {
|
||||
key: 'slack_username',
|
||||
group: 'slack',
|
||||
type: 'string'
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
const getMappedDeprecatedSettings = (settings) => {
|
||||
const mappedSettings = [];
|
||||
|
||||
for (const key in deprecatedSupportedSettingsOneToManyMap) {
|
||||
const deprecatedSetting = settings.find(setting => setting.key === key);
|
||||
|
||||
if (deprecatedSetting) {
|
||||
let deprecatedSettingValue;
|
||||
|
||||
try {
|
||||
deprecatedSettingValue = JSON.parse(deprecatedSetting.value);
|
||||
} catch (err) {
|
||||
// ignore the value if it's invalid
|
||||
}
|
||||
|
||||
if (deprecatedSettingValue) {
|
||||
deprecatedSupportedSettingsOneToManyMap[key].forEach(({from, to}) => {
|
||||
const value = _.get(deprecatedSettingValue, from);
|
||||
mappedSettings.push({
|
||||
key: to.key,
|
||||
value: value
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mappedSettings;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
browse(apiConfig, frame) {
|
||||
if (frame.options.type) {
|
||||
|
@ -48,8 +101,14 @@ module.exports = {
|
|||
return !settingFlagsArr.includes('RO');
|
||||
});
|
||||
|
||||
frame.data.settings = frame.data.settings.filter((setting) => {
|
||||
return setting.key !== 'bulk_email_settings';
|
||||
const mappedDeprecatedSettings = getMappedDeprecatedSettings(frame.data.settings);
|
||||
mappedDeprecatedSettings.forEach((setting) => {
|
||||
// NOTE: give priority for non-deprecated setting values if they exist
|
||||
const nonDeprecatedExists = frame.data.settings.find(s => s.key === setting.key);
|
||||
|
||||
if (!nonDeprecatedExists) {
|
||||
frame.data.settings.push(setting);
|
||||
}
|
||||
});
|
||||
|
||||
frame.data.settings.forEach((setting) => {
|
||||
|
@ -95,5 +154,10 @@ module.exports = {
|
|||
setting = url.forSetting(setting);
|
||||
}
|
||||
});
|
||||
|
||||
// Ignore all deprecated settings
|
||||
frame.data.settings = frame.data.settings.filter((setting) => {
|
||||
return DEPRECATED_SETTINGS.includes(setting.key) === false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -72,8 +72,12 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
if (frame.original.params.key === 'lang') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame.original.params.key === 'slack_url'
|
||||
|| frame.original.params.key === 'slack_username') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// CASE: edit
|
||||
if (frame.original.body && frame.original.body.settings) {
|
||||
frame.original.body.settings.forEach((setting) => {
|
||||
|
@ -89,6 +93,20 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
} else if (setting.key === 'default_locale') {
|
||||
const target = _.find(attrs, {key: 'lang'});
|
||||
target.key = 'default_locale';
|
||||
} else if (setting.key === 'slack') {
|
||||
const slackURL = _.cloneDeep(_.find(attrs, {key: 'slack_url'}));
|
||||
const slackUsername = _.cloneDeep(_.find(attrs, {key: 'slack_username'}));
|
||||
|
||||
if (slackURL || slackUsername) {
|
||||
const slack = slackURL || slackUsername;
|
||||
slack.key = 'slack';
|
||||
slack.value = JSON.stringify([{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}]);
|
||||
|
||||
attrs.push(slack);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -100,6 +118,8 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
const ghostFoot = _.cloneDeep(_.find(attrs, {key: 'codeinjection_foot'}));
|
||||
const timezone = _.cloneDeep(_.find(attrs, {key: 'timezone'}));
|
||||
const lang = _.cloneDeep(_.find(attrs, {key: 'lang'}));
|
||||
const slackURL = _.cloneDeep(_.find(attrs, {key: 'slack_url'}));
|
||||
const slackUsername = _.cloneDeep(_.find(attrs, {key: 'slack_username'}));
|
||||
|
||||
if (ghostHead) {
|
||||
ghostHead.key = 'ghost_head';
|
||||
|
@ -120,5 +140,16 @@ module.exports.forSettings = (attrs, frame) => {
|
|||
lang.key = 'default_locale';
|
||||
attrs.push(lang);
|
||||
}
|
||||
|
||||
if (slackURL || slackUsername) {
|
||||
const slack = slackURL || slackUsername;
|
||||
slack.key = 'slack';
|
||||
slack.value = [{
|
||||
url: slackURL && slackURL.value,
|
||||
username: slackUsername && slackUsername.value
|
||||
}];
|
||||
|
||||
attrs.push(slack);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -111,9 +111,25 @@ const mapSettings = (attrs, frame) => {
|
|||
// `forSettings` step. This logic can be rewritten once we get rid of deprecated
|
||||
// fields completely.
|
||||
if (_.isArray(attrs)) {
|
||||
attrs = _.filter(attrs, (o) => {
|
||||
return o.key !== 'ghost_head' && o.key !== 'ghost_foot';
|
||||
});
|
||||
const keysToFilter = ['ghost_head', 'ghost_foot'];
|
||||
|
||||
// NOTE: to support edits of deprecated 'slack' setting artificial 'slack_url' and 'slack_username'
|
||||
// were added to the request body in the input serializer. These should not be returned in response
|
||||
// body unless directly requested
|
||||
if (frame.original.body && frame.original.body.settings) {
|
||||
const requestedEditSlackUrl = frame.original.body.settings.find(s => s.key === 'slack_url');
|
||||
const requestedEditSlackUsername = frame.original.body.settings.find(s => s.key === 'slack_username');
|
||||
|
||||
if (!requestedEditSlackUrl) {
|
||||
keysToFilter.push('slack_url');
|
||||
}
|
||||
|
||||
if (!requestedEditSlackUsername) {
|
||||
keysToFilter.push('slack_username');
|
||||
}
|
||||
}
|
||||
|
||||
attrs = _.filter(attrs, attr => !(keysToFilter.includes(attr.key)));
|
||||
}
|
||||
|
||||
return attrs;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const debug = require('ghost-ignition').debug('importer:settings');
|
||||
const Promise = require('bluebird');
|
||||
const ObjectId = require('bson-objectid').default;
|
||||
const _ = require('lodash');
|
||||
const BaseImporter = require('./base');
|
||||
const models = require('../../../../models');
|
||||
|
@ -8,7 +9,8 @@ const keyGroupMapper = require('../../../../api/shared/serializers/input/utils/s
|
|||
const keyTypeMapper = require('../../../../api/shared/serializers/input/utils/settings-key-type-mapper');
|
||||
|
||||
const labsDefaults = JSON.parse(defaultSettings.labs.labs.defaultValue);
|
||||
const ignoredSettings = ['members_from_address', 'members_support_address'];
|
||||
const ignoredSettings = ['slack_url', 'members_from_address', 'members_support_address'];
|
||||
|
||||
// NOTE: drop support in Ghost 5.0
|
||||
const deprecatedSupportedSettingsMap = {
|
||||
default_locale: 'lang',
|
||||
|
@ -16,6 +18,17 @@ const deprecatedSupportedSettingsMap = {
|
|||
ghost_head: 'codeinjection_head',
|
||||
ghost_foot: 'codeinjection_foot'
|
||||
};
|
||||
const deprecatedSupportedSettingsOneToManyMap = {
|
||||
// NOTE: intentionally ignoring slack_url setting
|
||||
slack: [{
|
||||
from: '[0].username',
|
||||
to: {
|
||||
key: 'slack_username',
|
||||
group: 'slack',
|
||||
type: 'string'
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
const isFalse = (value) => {
|
||||
// Catches false, null, undefined, empty string
|
||||
|
@ -90,6 +103,44 @@ class SettingsImporter extends BaseImporter {
|
|||
return data;
|
||||
});
|
||||
|
||||
for (const key in deprecatedSupportedSettingsOneToManyMap) {
|
||||
const deprecatedSetting = this.dataToImport.find(setting => setting.key === key);
|
||||
|
||||
if (deprecatedSetting) {
|
||||
let deprecatedSettingValue;
|
||||
|
||||
try {
|
||||
deprecatedSettingValue = JSON.parse(deprecatedSetting.value);
|
||||
} catch (err) {
|
||||
this.problems.push({
|
||||
message: `Failed to parse the value of ${deprecatedSetting.key} setting value`,
|
||||
help: this.modelName,
|
||||
context: deprecatedSetting
|
||||
});
|
||||
}
|
||||
|
||||
if (deprecatedSettingValue) {
|
||||
deprecatedSupportedSettingsOneToManyMap[key].forEach(({from, to}) => {
|
||||
const value = _.get(deprecatedSettingValue, from);
|
||||
this.dataToImport.push({
|
||||
id: ObjectId.generate(),
|
||||
key: to.key,
|
||||
value: value,
|
||||
group: to.group,
|
||||
type: to.type,
|
||||
flags: null,
|
||||
created_by: deprecatedSetting.created_by,
|
||||
created_at: deprecatedSetting.created_at,
|
||||
updated_by: deprecatedSetting.updated_by,
|
||||
updated_at: deprecatedSetting.updated_at
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.dataToImport = _.filter(this.dataToImport, data => (key !== data.key));
|
||||
}
|
||||
|
||||
// NOTE: keep back compatibility with settings object structure present before migration
|
||||
// ref. https://github.com/TryGhost/Ghost/issues/10318
|
||||
this.dataToImport = this.dataToImport.map((data) => {
|
||||
|
@ -138,11 +189,6 @@ class SettingsImporter extends BaseImporter {
|
|||
obj.value = JSON.stringify(_.assign({}, JSON.parse(obj.value), labsDefaults));
|
||||
}
|
||||
|
||||
// CASE: we do not import slack hooks, otherwise it can happen very fast that you are pinging someone's slack channel
|
||||
if (obj.key === 'slack') {
|
||||
obj.value = JSON.stringify([{url: ''}]);
|
||||
}
|
||||
|
||||
// CASE: we do not import "from address" for members settings as that needs to go via validation with magic link
|
||||
if ((obj.key === 'members_from_address') || (obj.key === 'members_support_address')) {
|
||||
obj.value = null;
|
||||
|
|
|
@ -20,10 +20,13 @@ const defaultPostSlugs = [
|
|||
];
|
||||
|
||||
function getSlackSettings() {
|
||||
const setting = settingsCache.get('slack');
|
||||
// This might one day have multiple entries, for now its always a array
|
||||
// and we return the first item or an empty object
|
||||
return setting ? setting[0] : {};
|
||||
const username = settingsCache.get('slack_username');
|
||||
const url = settingsCache.get('slack_url');
|
||||
|
||||
return {
|
||||
username,
|
||||
url
|
||||
};
|
||||
}
|
||||
|
||||
function ping(post) {
|
||||
|
|
|
@ -50,7 +50,7 @@ describe('DB API', function () {
|
|||
Object.keys(jsonResponse.db[0].data).length.should.eql(34);
|
||||
});
|
||||
|
||||
it('Can import a JSON database', async function () {
|
||||
it('Can import a JSON database exported from Ghost v2', async function () {
|
||||
await request.delete(localUtils.API.getApiQuery('db/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -60,7 +60,61 @@ describe('DB API', function () {
|
|||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.attach('importfile', path.join(__dirname, '/../../utils/fixtures/export/default_export.json'))
|
||||
.attach('importfile', path.join(__dirname, '/../../utils/fixtures/export/v2_export.json'))
|
||||
.expect(200);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.db);
|
||||
should.exist(jsonResponse.problems);
|
||||
jsonResponse.problems.should.have.length(3);
|
||||
|
||||
const res2 = await request.get(localUtils.API.getApiQuery('posts/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
res2.body.posts.should.have.length(7);
|
||||
});
|
||||
|
||||
it('Can import a JSON database exported from Ghost v3', async function () {
|
||||
await request.delete(localUtils.API.getApiQuery('db/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect(204);
|
||||
|
||||
const res = await request.post(localUtils.API.getApiQuery('db/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.attach('importfile', path.join(__dirname, '/../../utils/fixtures/export/v3_export.json'))
|
||||
.expect(200);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.db);
|
||||
should.exist(jsonResponse.problems);
|
||||
jsonResponse.problems.should.have.length(3);
|
||||
|
||||
const res2 = await request.get(localUtils.API.getApiQuery('posts/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
res2.body.posts.should.have.length(7);
|
||||
});
|
||||
|
||||
it('Can import a JSON database exported from Ghost v4', async function () {
|
||||
await request.delete(localUtils.API.getApiQuery('db/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect(204);
|
||||
|
||||
const res = await request.post(localUtils.API.getApiQuery('db/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.attach('importfile', path.join(__dirname, '/../../utils/fixtures/export/v4_export.json'))
|
||||
.expect(200);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
|
|
|
@ -93,7 +93,14 @@ describe('Settings API', function () {
|
|||
},
|
||||
{
|
||||
key: 'slack',
|
||||
value: JSON.stringify({username: 'username'})
|
||||
value: JSON.stringify([{
|
||||
url: 'https://overrides.tld',
|
||||
username: 'Overrides Username'
|
||||
}])
|
||||
},
|
||||
{
|
||||
key: 'slack_username',
|
||||
value: 'New Slack Username'
|
||||
},
|
||||
{
|
||||
key: 'is_private',
|
||||
|
@ -160,6 +167,8 @@ describe('Settings API', function () {
|
|||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings.length.should.equal(17);
|
||||
|
||||
putBody.settings[0].key.should.eql('title');
|
||||
putBody.settings[0].value.should.eql(JSON.stringify(changedValue));
|
||||
|
||||
|
@ -169,8 +178,8 @@ describe('Settings API', function () {
|
|||
putBody.settings[2].key.should.eql('navigation');
|
||||
should.equal(putBody.settings[2].value, JSON.stringify({label: 'label1'}));
|
||||
|
||||
putBody.settings[3].key.should.eql('slack');
|
||||
should.equal(putBody.settings[3].value, JSON.stringify({username: 'username'}));
|
||||
putBody.settings[3].key.should.eql('slack_username');
|
||||
should.equal(putBody.settings[3].value, 'New Slack Username');
|
||||
|
||||
putBody.settings[4].key.should.eql('is_private');
|
||||
should.equal(putBody.settings[4].value, false);
|
||||
|
@ -211,6 +220,12 @@ describe('Settings API', function () {
|
|||
putBody.settings[15].key.should.eql('timezone');
|
||||
should.equal(putBody.settings[15].value, 'Pacific/Auckland');
|
||||
|
||||
putBody.settings[16].key.should.eql('slack');
|
||||
should.equal(putBody.settings[16].value, JSON.stringify([{
|
||||
url: 'https://overrides.tld',
|
||||
username: 'New Slack Username'
|
||||
}]));
|
||||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
});
|
||||
|
||||
|
|
|
@ -64,6 +64,8 @@ const defaultSettingsKeyTypes = [
|
|||
{key: 'amp_gtag_id', type: 'blog'},
|
||||
{key: 'labs', type: 'blog'},
|
||||
{key: 'slack', type: 'blog'},
|
||||
{key: 'slack_url', type: 'blog'},
|
||||
{key: 'slack_username', type: 'blog'},
|
||||
{key: 'unsplash', type: 'blog'},
|
||||
{key: 'shared_views', type: 'blog'},
|
||||
{key: 'active_timezone', type: 'blog'},
|
||||
|
@ -108,6 +110,7 @@ describe('Settings API (canary)', function () {
|
|||
|
||||
jsonResponse.settings.should.be.an.Object();
|
||||
const settings = jsonResponse.settings;
|
||||
|
||||
should.equal(settings.length, defaultSettingsKeyTypes.length);
|
||||
for (const defaultSetting of defaultSettingsKeyTypes) {
|
||||
should.exist(settings.find((setting) => {
|
||||
|
@ -171,6 +174,28 @@ describe('Settings API (canary)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('Requesting core settings type ignores the parameter and returns all settings', function () {
|
||||
return request.get(localUtils.API.getApiQuery(`settings/?type=core`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.settings);
|
||||
should.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.settings.should.be.an.Object();
|
||||
const settings = jsonResponse.settings;
|
||||
|
||||
Object.keys(settings).length.should.equal(68);
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse, 'settings');
|
||||
});
|
||||
});
|
||||
|
||||
it('Can\'t read core setting', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery('settings/db_hash/'))
|
||||
|
@ -195,6 +220,33 @@ describe('Settings API (canary)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('Can read slack_url introduced in v4', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/slack_url/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
jsonResponse.settings[0].key.should.eql('slack_url');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read deprecated default_locale', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/default_locale/'))
|
||||
.set('Origin', config.get('url'))
|
||||
|
@ -220,7 +272,7 @@ describe('Settings API (canary)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can edit deprecated default_locale setting', function () {
|
||||
it('Can edit deprecated default_locale setting', function () {
|
||||
return request.get(localUtils.API.getApiQuery('settings/default_locale/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -333,7 +385,32 @@ describe('Settings API (canary)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t read non existent setting', function (done) {
|
||||
it('Can read slack renamed&reformatted in v4', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/slack/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
jsonResponse.settings[0].key.should.eql('slack');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can\'t read non existent setting', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/testsetting/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -363,7 +440,7 @@ describe('Settings API (canary)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t edit permalinks', function (done) {
|
||||
it('Can\'t edit permalinks', function (done) {
|
||||
const settingToChange = {
|
||||
settings: [{key: 'permalinks', value: '/:primary_author/:slug/'}]
|
||||
};
|
||||
|
@ -383,7 +460,7 @@ describe('Settings API (canary)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t edit non existent setting', function () {
|
||||
it('Can\'t edit non existent setting', function () {
|
||||
return request.get(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -396,18 +473,15 @@ describe('Settings API (canary)', function () {
|
|||
should.exist(jsonResponse.settings);
|
||||
jsonResponse.settings = [{key: 'testvalue', value: newValue}];
|
||||
|
||||
return jsonResponse;
|
||||
})
|
||||
.then((jsonResponse) => {
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(jsonResponse)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(404)
|
||||
.then(function (res) {
|
||||
jsonResponse = res.body;
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
.then(function ({body, headers}) {
|
||||
jsonResponse = body;
|
||||
should.not.exist(headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
|
@ -461,6 +535,74 @@ describe('Settings API (canary)', function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Can edit multiple setting along with a deprecated one from v4', async function () {
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'slack',
|
||||
value: JSON.stringify([{
|
||||
url: 'https://newurl.tld/slack',
|
||||
username: 'New Slack Username'
|
||||
}])
|
||||
}, {
|
||||
key: 'title',
|
||||
value: 'Test site title'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const {body, headers} = await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
const putBody = body;
|
||||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings.length.should.equal(2);
|
||||
putBody.settings[0].key.should.eql('title');
|
||||
should.equal(putBody.settings[0].value, 'Test site title');
|
||||
|
||||
putBody.settings[1].key.should.eql('slack');
|
||||
should.equal(putBody.settings[1].value, JSON.stringify([{
|
||||
url: 'https://newurl.tld/slack',
|
||||
username: 'New Slack Username'
|
||||
}]));
|
||||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
});
|
||||
|
||||
it('Can edit a setting introduced in v4', async function () {
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'slack_username',
|
||||
value: 'can edit me'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const {body, headers} = await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
const putBody = body;
|
||||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings.length.should.equal(1);
|
||||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
putBody.settings[0].key.should.eql('slack_username');
|
||||
putBody.settings[0].value.should.eql('can edit me');
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Admin', function () {
|
||||
|
@ -519,7 +661,7 @@ describe('Settings API (canary)', function () {
|
|||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.then(function (res) {
|
||||
let jsonResponse = res.body;
|
||||
const newValue = 'new value';
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
jsonResponse.settings = [{key: 'visibility', value: 'public'}];
|
||||
|
|
|
@ -111,7 +111,7 @@ describe('Settings API (v2)', function () {
|
|||
for (const defaultSetting of defaultSettingsKeyTypes) {
|
||||
should.exist(settings.find((setting) => {
|
||||
return setting.key === defaultSetting.key && setting.type === defaultSetting.type;
|
||||
}));
|
||||
}), `Expected to find a setting with key ${defaultSetting.key} and type ${defaultSetting.type}`);
|
||||
}
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse, 'settings');
|
||||
|
@ -238,6 +238,21 @@ describe('Settings API (v2)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('Can\'t read slack_url introduced in v4', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/slack_url/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(404)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read default_locale deprecated in v3', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/default_locale/'))
|
||||
.set('Origin', config.get('url'))
|
||||
|
@ -338,7 +353,32 @@ describe('Settings API (v2)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t read non existent setting', function (done) {
|
||||
it('Can read slack renamed&reformatted in v4', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/slack/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
jsonResponse.settings[0].key.should.eql('slack');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can\'t read non existent setting', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/testsetting/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -368,7 +408,7 @@ describe('Settings API (v2)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t edit permalinks', function (done) {
|
||||
it('Can\'t edit permalinks', function (done) {
|
||||
const settingToChange = {
|
||||
settings: [{key: 'permalinks', value: '/:primary_author/:slug/'}]
|
||||
};
|
||||
|
@ -388,7 +428,7 @@ describe('Settings API (v2)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t edit non existent setting', function () {
|
||||
it('Can\'t edit non existent setting', function () {
|
||||
return request.get(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -445,7 +485,7 @@ describe('Settings API (v2)', function () {
|
|||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
request.put(localUtils.API.getApiQuery('settings/'))
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -463,6 +503,66 @@ describe('Settings API (v2)', function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Can edit a setting deprecated in v4', async function () {
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'slack',
|
||||
value: JSON.stringify([{
|
||||
url: 'https://newurl.tld/slack',
|
||||
username: 'New Slack Username'
|
||||
}])
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const {body, headers} = await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
const putBody = body;
|
||||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings.length.should.equal(1);
|
||||
putBody.settings[0].key.should.eql('slack');
|
||||
should.equal(putBody.settings[0].value, JSON.stringify([{
|
||||
url: 'https://newurl.tld/slack',
|
||||
username: 'New Slack Username'
|
||||
}]));
|
||||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
});
|
||||
|
||||
it('Ignores editing a setting introduced in v4', async function () {
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'slack_username',
|
||||
value: 'wont edit me'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const {body, headers} = await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
const putBody = body;
|
||||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings.length.should.equal(0);
|
||||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Admin', function () {
|
||||
|
|
|
@ -64,6 +64,8 @@ const defaultSettingsKeyTypes = [
|
|||
{key: 'amp_gtag_id', type: 'blog'},
|
||||
{key: 'labs', type: 'blog'},
|
||||
{key: 'slack', type: 'blog'},
|
||||
{key: 'slack_url', type: 'blog'},
|
||||
{key: 'slack_username', type: 'blog'},
|
||||
{key: 'unsplash', type: 'blog'},
|
||||
{key: 'shared_views', type: 'blog'},
|
||||
{key: 'active_timezone', type: 'blog'},
|
||||
|
@ -108,6 +110,7 @@ describe('Settings API (v3)', function () {
|
|||
|
||||
jsonResponse.settings.should.be.an.Object();
|
||||
const settings = jsonResponse.settings;
|
||||
|
||||
should.equal(settings.length, defaultSettingsKeyTypes.length);
|
||||
for (const defaultSetting of defaultSettingsKeyTypes) {
|
||||
should.exist(settings.find((setting) => {
|
||||
|
@ -189,7 +192,7 @@ describe('Settings API (v3)', function () {
|
|||
settings[0].key.should.equal('active_theme');
|
||||
settings[0].value.should.equal('casper');
|
||||
settings[0].type.should.equal('theme');
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'key', 'value', 'group', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
localUtils.API.checkResponse(jsonResponse, 'settings');
|
||||
});
|
||||
});
|
||||
|
@ -240,6 +243,33 @@ describe('Settings API (v3)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('Can read slack_url introduced in v4', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/slack_url/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
jsonResponse.settings[0].key.should.eql('slack_url');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read deprecated default_locale', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/default_locale/'))
|
||||
.set('Origin', config.get('url'))
|
||||
|
@ -265,7 +295,7 @@ describe('Settings API (v3)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can edit deprecated default_locale setting', function () {
|
||||
it('Can edit deprecated default_locale setting', function () {
|
||||
return request.get(localUtils.API.getApiQuery('settings/default_locale/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -378,7 +408,32 @@ describe('Settings API (v3)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t read non existent setting', function (done) {
|
||||
it('Can read slack renamed&reformatted in v4', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/slack/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
jsonResponse.settings[0].key.should.eql('slack');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can\'t read non existent setting', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/testsetting/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -408,7 +463,7 @@ describe('Settings API (v3)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t edit permalinks', function (done) {
|
||||
it('Can\'t edit permalinks', function (done) {
|
||||
const settingToChange = {
|
||||
settings: [{key: 'permalinks', value: '/:primary_author/:slug/'}]
|
||||
};
|
||||
|
@ -428,7 +483,7 @@ describe('Settings API (v3)', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('can\'t edit non existent setting', function () {
|
||||
it('Can\'t edit non existent setting', function () {
|
||||
return request.get(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
|
@ -441,18 +496,15 @@ describe('Settings API (v3)', function () {
|
|||
should.exist(jsonResponse.settings);
|
||||
jsonResponse.settings = [{key: 'testvalue', value: newValue}];
|
||||
|
||||
return jsonResponse;
|
||||
})
|
||||
.then((jsonResponse) => {
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(jsonResponse)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(404)
|
||||
.then(function (res) {
|
||||
jsonResponse = res.body;
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
.then(function ({body, headers}) {
|
||||
jsonResponse = body;
|
||||
should.not.exist(headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
|
@ -506,6 +558,74 @@ describe('Settings API (v3)', function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Can edit multiple setting along with a deprecated one from v4', async function () {
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'slack',
|
||||
value: JSON.stringify([{
|
||||
url: 'https://newurl.tld/slack',
|
||||
username: 'New Slack Username'
|
||||
}])
|
||||
}, {
|
||||
key: 'title',
|
||||
value: 'Test site title'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const {body, headers} = await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
const putBody = body;
|
||||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings.length.should.equal(2);
|
||||
putBody.settings[0].key.should.eql('title');
|
||||
should.equal(putBody.settings[0].value, 'Test site title');
|
||||
|
||||
putBody.settings[1].key.should.eql('slack');
|
||||
should.equal(putBody.settings[1].value, JSON.stringify([{
|
||||
url: 'https://newurl.tld/slack',
|
||||
username: 'New Slack Username'
|
||||
}]));
|
||||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
});
|
||||
|
||||
it('Can edit a setting introduced in v4', async function () {
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'slack_username',
|
||||
value: 'can edit me'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const {body, headers} = await request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
const putBody = body;
|
||||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings.length.should.equal(1);
|
||||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
putBody.settings[0].key.should.eql('slack_username');
|
||||
putBody.settings[0].value.should.eql('can edit me');
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Admin', function () {
|
||||
|
@ -564,7 +684,7 @@ describe('Settings API (v3)', function () {
|
|||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.then(function (res) {
|
||||
let jsonResponse = res.body;
|
||||
const newValue = 'new value';
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
jsonResponse.settings = [{key: 'visibility', value: 'public'}];
|
||||
|
|
|
@ -912,21 +912,39 @@ describe('Integration: Importer', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('does not import settings: slack hook, permalinks', function () {
|
||||
it('does not import settings: slack_url', function () {
|
||||
const exportData = exportedLatestBody().db[0];
|
||||
|
||||
exportData.data.settings[0] = testUtils.DataGenerator.forKnex.createSetting({
|
||||
key: 'slack',
|
||||
value: '[{\\"url\\":\\"https://hook.slack.com\\"}]'
|
||||
key: 'slack_url',
|
||||
value: 'https://ignoreme.tld'
|
||||
});
|
||||
|
||||
return dataImporter.doImport(exportData, importOptions)
|
||||
.then(function (imported) {
|
||||
imported.problems.length.should.eql(0);
|
||||
return models.Settings.findOne(_.merge({key: 'slack'}, testUtils.context.internal));
|
||||
return models.Settings.findOne(_.merge({key: 'slack_url'}, testUtils.context.internal));
|
||||
})
|
||||
.then(function (result) {
|
||||
result.attributes.value.should.eql('[{"url":""}]');
|
||||
result.attributes.value.should.eql('');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not import settings: slack_url from slack object', function () {
|
||||
const exportData = exportedLatestBody().db[0];
|
||||
|
||||
exportData.data.settings[0] = testUtils.DataGenerator.forKnex.createSetting({
|
||||
key: 'slack',
|
||||
value: '[{"url":"https://hook.slack.com"}]'
|
||||
});
|
||||
|
||||
return dataImporter.doImport(exportData, importOptions)
|
||||
.then(function (imported) {
|
||||
imported.problems.length.should.eql(0);
|
||||
return models.Settings.findOne(_.merge({key: 'slack_url'}, testUtils.context.internal));
|
||||
})
|
||||
.then(function (result) {
|
||||
result.attributes.value.should.eql('');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -95,5 +95,52 @@ describe('SettingsImporter', function () {
|
|||
|
||||
should.exist(problem);
|
||||
});
|
||||
|
||||
it('Adds a problem if unable to parse data from slack configuration', function () {
|
||||
const fakeSettings = [{
|
||||
key: 'slack',
|
||||
value: 'invalid JSON here'
|
||||
}];
|
||||
|
||||
const fakeExistingSettings = [{
|
||||
key: 'slack_username',
|
||||
value: 'Ghost'
|
||||
}];
|
||||
|
||||
const importer = new SettingsImporter({settings: fakeSettings}, {dataKeyToImport: 'settings'});
|
||||
|
||||
importer.existingData = fakeExistingSettings;
|
||||
importer.beforeImport();
|
||||
|
||||
const problem = find(importer.problems, {
|
||||
message: 'Failed to parse the value of slack setting value'
|
||||
});
|
||||
|
||||
should.exist(problem);
|
||||
});
|
||||
|
||||
it('Ignores slack URL from import files in all forms', function () {
|
||||
const fakeSettings = [{
|
||||
key: 'slack',
|
||||
value: `[{"url":"https://slack.url","username":"Test Name"}]`,
|
||||
created_at: '2021-02-10T01:26:08.452Z',
|
||||
updated_at: '2021-02-10T01:26:08.452Z'
|
||||
}, {
|
||||
key: 'slack_url',
|
||||
value: 'https://second-slack.url',
|
||||
created_at: '2021-02-10T01:26:08.452Z',
|
||||
updated_at: '2021-02-10T01:26:08.452Z'
|
||||
}];
|
||||
|
||||
const importer = new SettingsImporter({settings: fakeSettings}, {dataKeyToImport: 'settings'});
|
||||
|
||||
importer.beforeImport();
|
||||
|
||||
importer.problems.length.should.equal(0);
|
||||
|
||||
importer.dataToImport.length.should.equal(1);
|
||||
importer.dataToImport[0].key.should.equal('slack_username');
|
||||
importer.dataToImport[0].value.should.equal('Test Name');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,9 +15,7 @@ const schema = require('../../../core/server/data/schema').checks;
|
|||
const settingsCache = require('../../../core/server/services/settings/cache');
|
||||
|
||||
// Test data
|
||||
const slackObjNoUrl = [{url: ''}];
|
||||
|
||||
const slackObjWithUrl = [{url: 'https://hooks.slack.com/services/a-b-c-d'}];
|
||||
const slackURL = 'https://hooks.slack.com/services/a-b-c-d';
|
||||
|
||||
describe('Slack', function () {
|
||||
let eventStub;
|
||||
|
@ -130,7 +128,7 @@ describe('Slack', function () {
|
|||
urlService.getUrlByResourceId.withArgs(post.id, {absolute: true}).returns('http://myblog.com/' + post.slug + '/');
|
||||
|
||||
isPostStub.returns(true);
|
||||
settingsCacheStub.withArgs('slack').returns(slackObjWithUrl);
|
||||
settingsCacheStub.withArgs('slack_url').returns(slackURL);
|
||||
|
||||
// execute code
|
||||
ping(post);
|
||||
|
@ -139,12 +137,12 @@ describe('Slack', function () {
|
|||
makeRequestStub.calledOnce.should.be.true();
|
||||
isPostStub.calledTwice.should.be.true();
|
||||
urlService.getUrlByResourceId.calledOnce.should.be.true();
|
||||
settingsCacheStub.calledWith('slack').should.be.true();
|
||||
settingsCacheStub.calledWith('slack_url').should.be.true();
|
||||
|
||||
requestUrl = makeRequestStub.firstCall.args[0];
|
||||
requestData = JSON.parse(makeRequestStub.firstCall.args[1].body);
|
||||
|
||||
requestUrl.should.equal(slackObjWithUrl[0].url);
|
||||
requestUrl.should.equal(slackURL);
|
||||
requestData.attachments[0].title.should.equal(post.title);
|
||||
requestData.attachments[0].title_link.should.equal('http://myblog.com/webhook-test/');
|
||||
requestData.attachments[0].fields[0].value.should.equal('## markdown.');
|
||||
|
@ -160,7 +158,7 @@ describe('Slack', function () {
|
|||
let requestData;
|
||||
|
||||
isPostStub.returns(false);
|
||||
settingsCacheStub.withArgs('slack').returns(slackObjWithUrl);
|
||||
settingsCacheStub.withArgs('slack_url').returns(slackURL);
|
||||
|
||||
// execute code
|
||||
ping({message: 'Hi!'});
|
||||
|
@ -169,12 +167,12 @@ describe('Slack', function () {
|
|||
makeRequestStub.calledOnce.should.be.true();
|
||||
isPostStub.calledTwice.should.be.true();
|
||||
urlService.getUrlByResourceId.called.should.be.false();
|
||||
settingsCacheStub.calledWith('slack').should.be.true();
|
||||
settingsCacheStub.calledWith('slack_url').should.be.true();
|
||||
|
||||
requestUrl = makeRequestStub.firstCall.args[0];
|
||||
requestData = JSON.parse(makeRequestStub.firstCall.args[1].body);
|
||||
|
||||
requestUrl.should.equal(slackObjWithUrl[0].url);
|
||||
requestUrl.should.equal(slackURL);
|
||||
requestData.text.should.equal('Hi!');
|
||||
requestData.icon_url.should.equal('http://myblog.com/favicon.ico');
|
||||
requestData.username.should.equal('Ghost');
|
||||
|
@ -183,7 +181,7 @@ describe('Slack', function () {
|
|||
|
||||
it('makes a request and errors', function (done) {
|
||||
makeRequestStub.rejects();
|
||||
settingsCacheStub.withArgs('slack').returns(slackObjWithUrl);
|
||||
settingsCacheStub.withArgs('slack_url').returns(slackURL);
|
||||
|
||||
// execute code
|
||||
ping({});
|
||||
|
@ -201,7 +199,7 @@ describe('Slack', function () {
|
|||
it('does not make a request if post is a page', function () {
|
||||
const post = testUtils.DataGenerator.forKnex.createPost({type: 'page'});
|
||||
isPostStub.returns(true);
|
||||
settingsCacheStub.withArgs('slack').returns(slackObjWithUrl);
|
||||
settingsCacheStub.withArgs('slack_url').returns(slackURL);
|
||||
|
||||
// execute code
|
||||
ping(post);
|
||||
|
@ -210,13 +208,13 @@ describe('Slack', function () {
|
|||
makeRequestStub.calledOnce.should.be.false();
|
||||
isPostStub.calledOnce.should.be.true();
|
||||
urlService.getUrlByResourceId.calledOnce.should.be.true();
|
||||
settingsCacheStub.calledWith('slack').should.be.true();
|
||||
settingsCacheStub.calledWith('slack_url').should.be.true();
|
||||
});
|
||||
|
||||
it('does not send webhook for \'welcome\' post', function () {
|
||||
const post = testUtils.DataGenerator.forKnex.createPost({slug: 'welcome'});
|
||||
isPostStub.returns(true);
|
||||
settingsCacheStub.withArgs('slack').returns(slackObjWithUrl);
|
||||
settingsCacheStub.withArgs('slack_url').returns(slackURL);
|
||||
|
||||
// execute code
|
||||
ping(post);
|
||||
|
@ -225,12 +223,12 @@ describe('Slack', function () {
|
|||
makeRequestStub.calledOnce.should.be.false();
|
||||
isPostStub.calledOnce.should.be.true();
|
||||
urlService.getUrlByResourceId.calledOnce.should.be.true();
|
||||
settingsCacheStub.calledWith('slack').should.be.true();
|
||||
settingsCacheStub.calledWith('slack_url').should.be.true();
|
||||
});
|
||||
|
||||
it('handles broken slack settings', function () {
|
||||
const post = testUtils.DataGenerator.forKnex.createPost({slug: 'any'});
|
||||
settingsCacheStub.withArgs('slack').returns();
|
||||
settingsCacheStub.withArgs('slack_url').returns();
|
||||
|
||||
// execute code
|
||||
ping(post);
|
||||
|
@ -239,7 +237,7 @@ describe('Slack', function () {
|
|||
makeRequestStub.calledOnce.should.be.false();
|
||||
isPostStub.calledOnce.should.be.true();
|
||||
urlService.getUrlByResourceId.called.should.be.false();
|
||||
settingsCacheStub.calledWith('slack').should.be.true();
|
||||
settingsCacheStub.calledWith('slack_url').should.be.true();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
2540
test/utils/fixtures/export/v3_export.json
Normal file
2540
test/utils/fixtures/export/v3_export.json
Normal file
File diff suppressed because it is too large
Load diff
3002
test/utils/fixtures/export/v4_export.json
Normal file
3002
test/utils/fixtures/export/v4_export.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue