mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
refs https://github.com/TryGhost/Team/issues/1599 - adds `portal_*` settings to public settings endpoint - adds calculated `firstpromoter_account` setting for public settings endpoint - also adds Ghost `version` information
184 lines
5.9 KiB
JavaScript
184 lines
5.9 KiB
JavaScript
/**
|
|
* Settings Lib
|
|
* A collection of utilities for handling settings including a cache
|
|
*/
|
|
const errors = require('@tryghost/errors');
|
|
const tpl = require('@tryghost/tpl');
|
|
|
|
const events = require('../../lib/common/events');
|
|
const models = require('../../models');
|
|
const labs = require('../../../shared/labs');
|
|
const config = require('../../../shared/config');
|
|
const SettingsCache = require('../../../shared/settings-cache');
|
|
const SettingsBREADService = require('./settings-bread-service');
|
|
const {obfuscatedSetting, isSecretSetting, hideValueIfSecret} = require('./settings-utils');
|
|
|
|
const ObjectId = require('bson-objectid');
|
|
|
|
const messages = {
|
|
incorrectKeyType: 'type must be one of "direct" or "connect".'
|
|
};
|
|
|
|
/**
|
|
* @returns {SettingsBREADService} instance of the PostsService
|
|
*/
|
|
const getSettingsBREADServiceInstance = () => {
|
|
return new SettingsBREADService({
|
|
SettingsModel: models.Settings,
|
|
settingsCache: SettingsCache,
|
|
labsService: labs
|
|
});
|
|
};
|
|
|
|
class CalculatedField {
|
|
constructor({key, type, group, fn, dependents}) {
|
|
this.key = key;
|
|
this.type = type;
|
|
this.group = group;
|
|
this.fn = fn;
|
|
this.dependents = dependents;
|
|
}
|
|
|
|
getSetting() {
|
|
return {
|
|
key: this.key,
|
|
type: this.type,
|
|
group: this.group,
|
|
value: this.fn(),
|
|
// @TODO: remove this hack
|
|
id: ObjectId().toHexString(),
|
|
created_at: new Date().toISOString().replace(/\d{3}Z$/, '000Z'),
|
|
updated_at: new Date().toISOString().replace(/\d{3}Z$/, '000Z')
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
/**
|
|
* Initialize the cache, used in boot and in testing
|
|
*/
|
|
async init() {
|
|
const settingsCollection = await models.Settings.populateDefaults();
|
|
SettingsCache.init(events, settingsCollection, this.getCalculatedFields());
|
|
},
|
|
|
|
/**
|
|
* Restore the cache, used during e2e testing only
|
|
*/
|
|
reset() {
|
|
SettingsCache.reset(events);
|
|
},
|
|
|
|
isMembersEnabled() {
|
|
return SettingsCache.get('members_signup_access') !== 'none';
|
|
},
|
|
|
|
isMembersInviteOnly() {
|
|
return SettingsCache.get('members_signup_access') === 'invite';
|
|
},
|
|
|
|
/**
|
|
* @param {'direct' | 'connect'} type - The "type" of keys to fetch from settings
|
|
* @returns {{publicKey: string, secretKey: string} | null}
|
|
*/
|
|
getStripeKeys(type) {
|
|
if (type !== 'direct' && type !== 'connect') {
|
|
throw new errors.IncorrectUsageError({message: tpl(messages.incorrectKeyType)});
|
|
}
|
|
|
|
const secretKey = SettingsCache.get(`stripe_${type === 'connect' ? 'connect_' : ''}secret_key`);
|
|
const publicKey = SettingsCache.get(`stripe_${type === 'connect' ? 'connect_' : ''}publishable_key`);
|
|
|
|
if (!secretKey || !publicKey) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
secretKey,
|
|
publicKey
|
|
};
|
|
},
|
|
|
|
/**
|
|
* @returns {{publicKey: string, secretKey: string} | null}
|
|
*/
|
|
getActiveStripeKeys() {
|
|
const stripeDirect = config.get('stripeDirect');
|
|
|
|
if (stripeDirect) {
|
|
return this.getStripeKeys('direct');
|
|
}
|
|
|
|
const connectKeys = this.getStripeKeys('connect');
|
|
|
|
if (!connectKeys) {
|
|
return this.getStripeKeys('direct');
|
|
}
|
|
|
|
return connectKeys;
|
|
},
|
|
|
|
isStripeConnected() {
|
|
return this.isMembersEnabled() && this.getActiveStripeKeys() !== null;
|
|
},
|
|
|
|
getFirstpromoterId() {
|
|
if (!SettingsCache.get('firstpromoter')) {
|
|
return null;
|
|
}
|
|
return SettingsCache.get('firstpromoter_id');
|
|
},
|
|
|
|
/**
|
|
*
|
|
*/
|
|
getCalculatedFields() {
|
|
const fields = [];
|
|
|
|
fields.push(new CalculatedField({key: 'members_enabled', type: 'boolean', group: 'members', fn: this.isMembersEnabled.bind(this), dependents: ['members_signup_access']}));
|
|
fields.push(new CalculatedField({key: 'members_invite_only', type: 'boolean', group: 'members', fn: this.isMembersInviteOnly.bind(this), dependents: ['members_signup_access']}));
|
|
fields.push(new CalculatedField({key: 'paid_members_enabled', type: 'boolean', group: 'members', fn: this.isStripeConnected.bind(this), dependents: ['members_signup_access', 'stripe_secret_key', 'stripe_publishable_key', 'stripe_connect_secret_key', 'stripe_connect_publishable_key']}));
|
|
fields.push(new CalculatedField({key: 'firstpromoter_account', type: 'string', group: 'firstpromoter', fn: this.getFirstpromoterId.bind(this), dependents: ['firstpromoter', 'firstpromoter_id']}));
|
|
|
|
return fields;
|
|
},
|
|
|
|
/**
|
|
* Handles synchronization of routes.yaml hash loaded in the frontend with
|
|
* the value stored in the settings table.
|
|
* getRoutesHash is a function to allow keeping "frontend" decoupled from settings
|
|
*
|
|
* @param {function} getRoutesHash function fetching currently loaded routes file hash
|
|
*/
|
|
async syncRoutesHash(getRoutesHash) {
|
|
const currentRoutesHash = await getRoutesHash();
|
|
|
|
if (SettingsCache.get('routes_hash') !== currentRoutesHash) {
|
|
return await models.Settings.edit([{
|
|
key: 'routes_hash',
|
|
value: currentRoutesHash
|
|
}], {context: {internal: true}});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles email setting synchronization when email has been verified per instance
|
|
*
|
|
* @param {boolean} configValue current email verification value from local config
|
|
*/
|
|
async syncEmailSettings(configValue) {
|
|
const isEmailDisabled = SettingsCache.get('email_verification_required');
|
|
|
|
if (configValue === true && isEmailDisabled) {
|
|
return await models.Settings.edit([{
|
|
key: 'email_verification_required',
|
|
value: false
|
|
}], {context: {internal: true}});
|
|
}
|
|
},
|
|
|
|
obfuscatedSetting,
|
|
isSecretSetting,
|
|
hideValueIfSecret,
|
|
getSettingsBREADServiceInstance
|
|
};
|