ghost
Version:
The professional publishing platform
135 lines (122 loc) • 4.15 kB
JavaScript
const _ = require('lodash');
const url = require('./utils/url');
const localUtils = require('../../index');
const settingsCache = require('../../../../../../shared/settings-cache');
const {WRITABLE_KEYS_ALLOWLIST} = require('../../../../../../shared/labs');
const EDITABLE_SETTINGS = [
'title',
'description',
'logo',
'cover_image',
'icon',
'locale',
'timezone',
'codeinjection_head',
'codeinjection_foot',
'facebook',
'twitter',
'navigation',
'secondary_navigation',
'meta_title',
'meta_description',
'og_image',
'og_title',
'og_description',
'twitter_image',
'twitter_title',
'twitter_description',
'is_private',
'password',
'default_content_visibility',
'default_content_visibility_tiers',
'members_signup_access',
'members_support_address',
'stripe_secret_key',
'stripe_publishable_key',
'stripe_connect_integration_token',
'portal_name',
'portal_button',
'portal_plans',
'portal_default_plan',
'portal_button_style',
'firstpromoter',
'firstpromoter_id',
'portal_button_icon',
'portal_button_signup_text',
'portal_signup_terms_html',
'portal_signup_checkbox_required',
'mailgun_api_key',
'mailgun_domain',
'mailgun_base_url',
'email_track_opens',
'email_track_clicks',
'members_track_sources',
'web_analytics',
'amp',
'amp_gtag_id',
'slack_url',
'slack_username',
'unsplash',
'shared_views',
'accent_color',
'editor_default_email_recipients',
'editor_default_email_recipients_filter',
'labs',
'comments_enabled',
'outbound_link_tagging',
'announcement_content',
'announcement_background',
'announcement_visibility',
'pintura',
'pintura_js_url',
'pintura_css_url',
'donations_currency',
'donations_suggested_amount',
'recommendations_enabled',
'body_font',
'heading_font',
'blocked_email_domains',
'require_email_mfa',
'social_web',
'explore_ping',
'explore_ping_growth'
];
module.exports = {
edit(apiConfig, frame) {
// CASE: allow shorthand syntax where a single key and value are passed to edit instead of object and options
if (_.isString(frame.data)) {
frame.data = {settings: [{key: frame.data, value: frame.options}]};
}
const settings = settingsCache.getAll();
if (!localUtils.isInternal(frame)) {
// Ignore and drop all values not in the EDITABLE_SETTINGS list unless this is an internal request
frame.data.settings = frame.data.settings.filter((setting) => {
return EDITABLE_SETTINGS.includes(setting.key);
});
}
frame.data.settings.forEach((setting) => {
const settingType = settings[setting.key] ? settings[setting.key].type : '';
// @TODO: handle these transformations in a centralized API place (these rules should apply for ALL resources)
// CASE: Ensure we won't forward strings, otherwise model events or model interactions can fail
if (settingType === 'boolean' && (setting.value === '0' || setting.value === '1')) {
setting.value = !!+setting.value;
}
// CASE: Ensure we won't forward strings, otherwise model events or model interactions can fail
if (settingType === 'boolean' && (setting.value === 'false' || setting.value === 'true')) {
setting.value = setting.value === 'true';
}
// CASE: filter labs to allowlist
if (setting.key === 'labs') {
const inputLabsValue = JSON.parse(setting.value);
const filteredLabsValue = {};
for (const flag in inputLabsValue) {
if (WRITABLE_KEYS_ALLOWLIST.includes(flag)) {
filteredLabsValue[flag] = inputLabsValue[flag];
}
}
setting.value = JSON.stringify(filteredLabsValue);
}
setting = url.forSetting(setting);
});
}
};