Merge pull request #2980 from jgable/lazyLoadDefaultSettings

Lazy load default settings
This commit is contained in:
Sebastian Gierlinger 2014-06-17 21:52:34 +02:00
commit a3665cd917
4 changed files with 122 additions and 42 deletions

View File

@ -17,6 +17,8 @@ var _ = require('lodash'),
readSettingsResult, readSettingsResult,
settingsResult, settingsResult,
canEditAllSettings, canEditAllSettings,
populateDefaultSetting,
hasPopulatedDefaults = false,
/** /**
* ## Cache * ## Cache
@ -183,6 +185,38 @@ settingsResult = function (settings, type) {
return result; return result;
}; };
/**
* ### Populate Default Setting
* @private
* @param key
* @param type
* @returns Promise(Setting)
*/
populateDefaultSetting = function (key) {
// Call populateDefault and update the settings cache
return dataProvider.Settings.populateDefault(key).then(function (defaultSetting) {
// Process the default result and add to settings cache
var readResult = readSettingsResult(defaultSetting);
// Add to the settings cache
return updateSettingsCache(readResult).then(function () {
// Update theme with the new settings
return config.theme.update(settings, config().url);
}).then(function () {
// Get the result from the cache with permission checks
return defaultSetting;
});
}).otherwise(function (err) {
// Pass along NotFoundError
if (typeof err === errors.NotFoundError) {
return when.reject(err);
}
// TODO: Different kind of error?
return when.reject(new errors.NotFoundError('Problem finding setting: ' + key));
});
};
/** /**
* ### Can Edit All Settings * ### Can Edit All Settings
* Check that this edit request is allowed for all settings requested to be updated * Check that this edit request is allowed for all settings requested to be updated
@ -191,20 +225,27 @@ settingsResult = function (settings, type) {
* @returns {*} * @returns {*}
*/ */
canEditAllSettings = function (settingsInfo, options) { canEditAllSettings = function (settingsInfo, options) {
var checks = _.map(settingsInfo, function (settingInfo) { var checkSettingPermissions = function (setting) {
var setting = settingsCache[settingInfo.key];
if (!setting) {
return when.reject(new errors.NotFoundError('Unable to find setting: ' + settingInfo.key));
}
if (setting.type === 'core' && !(options.context && options.context.internal)) { if (setting.type === 'core' && !(options.context && options.context.internal)) {
return when.reject( return when.reject(
new errors.NoPermissionError('Attempted to access core setting from external request') new errors.NoPermissionError('Attempted to access core setting from external request')
); );
} }
return canThis(options.context).edit.setting(settingInfo.key); return canThis(options.context).edit.setting(setting.key);
},
checks = _.map(settingsInfo, function (settingInfo) {
var setting = settingsCache[settingInfo.key];
if (!setting) {
// Try to populate a default setting if not in the cache
return populateDefaultSetting(settingInfo.key).then(function (defaultSetting) {
// Get the result from the cache with permission checks
return checkSettingPermissions(defaultSetting);
});
}
return checkSettingPermissions(setting);
}); });
return when.all(checks); return when.all(checks);
@ -223,6 +264,14 @@ settings = {
* @returns {*} * @returns {*}
*/ */
browse: function browse(options) { browse: function browse(options) {
// First, check if we have populated the settings from default-settings yet
if (!hasPopulatedDefaults) {
return dataProvider.Settings.populateDefaults().then(function () {
hasPopulatedDefaults = true;
return settings.browse(options);
});
}
options = options || {}; options = options || {};
var result = settingsResult(settingsCache, options.type); var result = settingsResult(settingsCache, options.type);
@ -253,13 +302,10 @@ settings = {
options = { key: options }; options = { key: options };
} }
var getSettingsResult = function () {
var setting = settingsCache[options.key], var setting = settingsCache[options.key],
result = {}; result = {};
if (!setting) {
return when.reject(new errors.NotFoundError('Unable to find setting: ' + options.key));
}
result[options.key] = setting; result[options.key] = setting;
if (setting.type === 'core' && !(options.context && options.context.internal)) { if (setting.type === 'core' && !(options.context && options.context.internal)) {
@ -277,6 +323,19 @@ settings = {
}, function () { }, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to read settings.')); return when.reject(new errors.NoPermissionError('You do not have permission to read settings.'));
}); });
};
// If the setting is not already in the cache
if (!settingsCache[options.key]) {
// Try to populate the setting from default-settings file
return populateDefaultSetting(options.key).then(function () {
// Get the result from the cache with permission checks
return getSettingsResult();
});
}
// Get the result from the cache with permission checks
return getSettingsResult();
}, },
/** /**

View File

@ -13,9 +13,7 @@ var _ = require('lodash'),
function getDefaultDatabaseVersion() { function getDefaultDatabaseVersion() {
if (!defaultDatabaseVersion) { if (!defaultDatabaseVersion) {
// This be the current version according to the software // This be the current version according to the software
defaultDatabaseVersion = _.find(defaultSettings.core, function (setting) { defaultDatabaseVersion = defaultSettings.core.databaseVersion.defaultValue;
return setting.key === 'databaseVersion';
}).defaultValue;
} }
return defaultDatabaseVersion; return defaultDatabaseVersion;

View File

@ -215,9 +215,6 @@ function init(server) {
return builtFilesExist().then(function () { return builtFilesExist().then(function () {
// Initialise the models // Initialise the models
return models.init(); return models.init();
}).then(function () {
// Populate any missing default settings
return models.Settings.populateDefaults();
}).then(function () { }).then(function () {
// Initialize the settings cache // Initialize the settings cache
return api.init(); return api.init();

View File

@ -25,7 +25,14 @@ function parseDefaultSettings() {
return defaultSettingsFlattened; return defaultSettingsFlattened;
} }
function getDefaultSettings() {
if (!defaultSettings) {
defaultSettings = parseDefaultSettings(); defaultSettings = parseDefaultSettings();
}
return defaultSettings;
}
// Each setting is saved as a separate row in the database, // Each setting is saved as a separate row in the database,
// but the overlying API treats them as a single key:value mapping // but the overlying API treats them as a single key:value mapping
@ -43,7 +50,7 @@ Settings = ghostBookshelf.Model.extend({
validate: function () { validate: function () {
var self = this; var self = this;
return when(validation.validateSchema(self.tableName, self.toJSON())).then(function () { return when(validation.validateSchema(self.tableName, self.toJSON())).then(function () {
return validation.validateSettings(defaultSettings, self); return validation.validateSettings(getDefaultSettings(), self);
}); });
}, },
@ -117,12 +124,31 @@ Settings = ghostBookshelf.Model.extend({
}); });
}, },
populateDefault: function (key) {
if (!getDefaultSettings()[key]) {
return when.reject(new errors.NotFoundError('Unable to find default setting: ' + key));
}
// TOOD: databaseVersion and currentVersion special cases?
this.findOne({ key: key }).then(function (foundSetting) {
if (foundSetting) {
return foundSetting;
}
var defaultSetting = _.clone(getDefaultSettings()[key]);
defaultSetting.value = defaultSetting.defaultValue;
return Settings.forge(defaultSetting).save(null, {user: 1});
});
},
populateDefaults: function () { populateDefaults: function () {
return this.findAll().then(function (allSettings) { return this.findAll().then(function (allSettings) {
var usedKeys = allSettings.models.map(function (setting) { return setting.get('key'); }), var usedKeys = allSettings.models.map(function (setting) { return setting.get('key'); }),
insertOperations = []; insertOperations = [];
_.each(defaultSettings, function (defaultSetting, defaultSettingKey) { _.each(getDefaultSettings(), function (defaultSetting, defaultSettingKey) {
var isMissingFromDB = usedKeys.indexOf(defaultSettingKey) === -1; var isMissingFromDB = usedKeys.indexOf(defaultSettingKey) === -1;
// Temporary code to deal with old databases with currentVersion settings // Temporary code to deal with old databases with currentVersion settings
if (defaultSettingKey === 'databaseVersion' && usedKeys.indexOf('currentVersion') !== -1) { if (defaultSettingKey === 'databaseVersion' && usedKeys.indexOf('currentVersion') !== -1) {